Sizeof在模板中失败,即使类型都已定义
Sizeof failing in template even though types are all defined
好的,我正在使用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应该得到很好的定义。这里有我遗漏的东西吗?
--Ron
问题是编译器试图在实例化functor<>
之前先实例化mempool<>
。这是因为编译器认为在functor<>
本身被认为是完全定义之前,它需要能够首先定义静态成员functor<>::pool
。
解决方法是从静态成员函数返回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
中的静态对象可以被正确地实例化。
附带说明一下,将不完整类型作为参数传递给模板是可以接受的,但模板对不完整类型的实际操作有限制。如果模板只需要一个引用或指针来实例化类型,那么一切都很好。
您对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;
}
根据你的应用程序,你应该能够使用类型特征来做你想做的事情。
在functor
的内部声明pool
时,您仍在定义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
我认为你做不到,因为你有一个递归定义。例如,你不能这样做:
#include <cstdlib>
class B;
class A
{
B b;
};
class B
{
A a;
};
int main()
{
A x;
}
唯一的解决方法是使其中一个成员成为指针而不是实例。
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 列表参数的类型定义
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 关于 C++ 中的函数类型定义
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- 将使用/类型定义限制为类范围
- 模板类型定义?
- C++:模板类的类型定义
- 如何对命名空间限定类型进行类型定义?
- 此递归模板类型定义是否有效C++?
- 具有调整对齐方式的类型定义
- C++从抽象类型定义类成员
- 用于C++代码的 API 监视器类型定义 (XML)
- 如何将result_of与函数类型定义一起使用
- 在C++的适当类型定义位置
- 如何根据模板类型定义浮点常量?
- 如何为缺少预定义运算符而不扩展命名空间"std"的标准类型定义运算符>> (istream &, ...)?
- 参数化类的别名(或类型定义)内部类
- 如果我想从类型"T"定义元素的容器(来自 STL),那么"T"必须使用默认构造函数?