好的,我正在使用g ++ 4.8.2并且有以下(有点长)代码,它会收到有关不完整类型的错误消息。我已将代码缩减为较小的块以包含在此处,并且可以直接编译:
#include <cstdlib>
struct S
{
void method(){}
};
template<size_t sz, size_t tot>
class genpool
{
};
template <class T>
class mempool
{
private:
genpool<sizeof(T), 10*sizeof(T)> p;
};
template <class obj, class mthd>
class functor
{
private:
static mempool<functor<obj, mthd> > pool;
};
template <class obj, class mthd>
mempool<functor<obj, mthd> > functor<obj, mthd>::pool;
int main()
{
typedef void (S::*m)();
typedef functor<S, m> fctr;
fctr f;
}
编译器错误消息是:
g++ jj.C
jj.C: In instantiation of ‘class mempool<functor<S, void (S::*)()> >’:
jj.C:30:30: required from ‘class functor<S, void (S::*)()>’
jj.C:37:8: required from here
jj.C:18:17: error: invalid application of ‘sizeof’ to incomplete type ‘functor<S, void (S::*)()>’
genpool<sizeof(T), 10*sizeof(T)> p;
^
Compilation exited abnormally with code 1 at Thu Apr 9 18:50:06
显然,上面定义了模板仿函数,并且已经明确定义了仿函数的所有参数。这似乎意味着我应该很好地定义sizeof函数。我在这里找不到什么东西吗?
- 罗恩
答案 0 :(得分:6)
问题是编译器在实例化mempool<>
之前尝试实例化functor<>
。这是因为编译器认为在functor<>::pool
本身被认为是完全定义之前,它需要能够首先定义静态成员functor<>
。
解决方法是从静态成员函数返回mempool<> &
。
template <class obj, class mthd>
class functor
{
private:
static mempool<functor> & get_pool () {
static mempool<functor> pool;
return pool;
}
};
//template <class obj, class mthd>
//mempool<functor<obj, mthd> > functor<obj, mthd>::pool;
这是有效的,因为引用意味着mempool<>
在实例化functor<>
之前保持不完整是可以的。 (实际上,除非存在实际调用它的代码,否则不会实例化模板的方法。)当调用静态方法时,functor<>
本身就完成了,因此functor<>::get_pool
中的静态对象可以正确实例
<子> 作为旁注,将不完整类型作为参数传递给模板是可以接受的,但模板对不完整类型实际执行的操作有限制。如果模板只需要一个引用或指向其实例化类型的指针,那么一切都很好。 子>
答案 1 :(得分:1)
您对functor
的定义是递归的。它要求编译器在确定functor
类型时知道functor
类型的大小。您可以使用此代码生成完全相同的问题:
template <class A>
class B {
public:
static const int szA = sizeof(A);
};
template <class A>
class C {
public:
static B<C<A> > b;
};
int main() {
C<int> c;
}
根据您的应用程序的不同,您应该可以使用type traits执行所需的操作。
答案 2 :(得分:1)
当您在pool
中声明functor
时,您仍在定义functor
类,因此类型functor
仍然是不完整的。
这与前向声明类似:
class functor;
functor func; <<-incomplete here
functor *ptr; <<-pointer is fine
class functor
{
functor func; <<-incomplete again
};
functor func; <<-now complete definition, ok
答案 3 :(得分:0)
我认为你不能这样做,因为你有一个递归的定义。例如,您无法执行此操作:
#include <cstdlib>
class B;
class A
{
B b;
};
class B
{
A a;
};
int main()
{
A x;
}
唯一的出路是让其中一个成员成为指针而不是实例。