我编辑了原始问题。
我试图在模板化的类中使用自我实现的静态分配器,我收到此错误:
error: invalid application of 'sizeof' to incomplete type
我试图最小化代码但仍然保留错误,这就是我得到的:
template<typename T>
struct allocator_t {
unsigned char blk[sizeof(T)];
};
template<typename t_value_t, int t_max_nodes>
class foo_c {
private:
typedef allocator_t<foo_c> bar_allocator_t;
static bar_allocator_t m_allocator;
};
template<typename t_value_t, int t_max_nodes>
typename foo_c<t_value_t, t_max_nodes>::bar_allocator_t
foo_c<t_value_t, t_max_nodes>::bar_t::m_allocator;
struct some_t {
explicit some_t(void) {}
};
void func(void) {
foo_c<some_t, 10> a;
}
完整的错误堆栈是这样的:
template_static_example.cc: In instantiation of 'allocator_t<foo_c<some_t, 10> >':
template_static_example.cc:21:2: instantiated from 'foo_c<some_t, 10>'
template_static_example.cc:30:21: instantiated from here
template_static_example.cc:3:30: error: invalid application of 'sizeof' to incomplete type 'foo_c<some_t, 10>'
我有其他基本上使用相同技术的模块,一切都很棒。
这些模块与我试图制作的新模块之间的区别在于新模块是模板化的,实际上,上面的代码(减去模板)编译时没有错误:
template<typename T>
struct allocator_t {
unsigned char blk[sizeof(T)];
};
class foo_c {
private:
typedef allocator_t<foo_c> bar_allocator_t;
static bar_allocator_t m_allocator;
};
foo_c::bar_allocator_t foo_c::m_allocator;
struct some_t {
explicit some_t(void) {}
};
void func(void) {
foo_c a;
}
我可以给出的另一个输入是,当我使用clang
编译时,两者都编译没有错误。但是,g++
仅接受非模板化版本。
答案 0 :(得分:1)
您的问题是您的bar_allocator_t
是在bar_t
内宣布的。分配器在编译期间尝试获取bar_t
的大小:
unsigned char blk[sizeof(T)];
但它还没有完成定义结构,所以它不知道大小是什么:
struct bar_t {
explicit bar_t(void) {};
~bar_t(void);
private:
typedef allocator_t<bar_t> bar_allocator_t;
static bar_allocator_t m_allocator; // We don't know the size of `bar_t` here
};
我不确定哪种解决方案对您有用,但您可能需要将分配器移到结构外部,或者您可以使用动态内存:
template<typename t_value_t, int t_max_nodes>
class foo_c {
private:
struct bar_t {
explicit bar_t(void) {};
~bar_t(void);
private:
typedef allocator_t<bar_t> bar_allocator_t;
static bar_allocator_t * m_allocator;
};
bar_t m_root;
};
template<typename t_value_t, int t_max_nodes>
typename foo_c<t_value_t, t_max_nodes>::bar_t::bar_allocator_t *
foo_c<t_value_t, t_max_nodes>::bar_t::m_allocator =
new typename foo_c<t_value_t, t_max_nodes>::bar_t::bar_allocator_t;
答案 1 :(得分:1)
我认为事情的核心foo_c
不完整,因为它的大小取决于allocator_t
的大小,但allocator_t
取决于foo_c
的大小。< / p>
如果我们改为foo_c
指向allocator_t<foo_c>
,那么事情就可以了,因为这是我们可以用不完整类型做的少数事情之一。
template<typename t_value_t, int t_max_nodes>
class foo_c {
private:
typedef allocator_t<foo_c> bar_allocator_t;
static std::unique_ptr<bar_allocator_t> m_allocator;
};
template<typename t_value_t, int t_max_nodes>
std::unique_ptr<typename foo_c<t_value_t, t_max_nodes>::bar_allocator_t>
foo_c<t_value_t, t_max_nodes>::m_allocator;
看起来GCC和Clang will compile your code只要你转发声明allocator_t
,然后放置它的定义,但我不确定这是定义的行为。