我一直在研究这个问题,但还没有找到解决方案。基本上我需要在模板类中初始化一个静态const类型变量。
class MyType
{
public:
MyType (int a, int b) { }
};
template <class T>
class MyClass
{
public:
static const MyType Type;
};
在cpp内初始化Type会产生链接器错误。在标头内初始化类型将导致它多次初始化。由于它是非整数类型,因此无法在类中初始化类型。如何在不限制类专业化的情况下解决此问题。任何帮助表示赞赏。
答案 0 :(得分:3)
我不确定你的意思是“在cpp中初始化Type会产生链接器错误。”但假设你实际上意味着定义然后你必须做错了,因为在适当的位置定义每个类型的静态成员肯定有效!您在类模板中拥有的是对象的声明,如果它曾被引用,则需要在某处定义。只有当MyType
碰巧是一个整数类型时,你才在类[模板]中初始化它,并且你永远不需要它的地址(例如将它绑定到一个常量引用或取其地址)你没有定义它。这是因为在这种情况下它总是被视为常量表达式。
我的猜测是你试图在某个cpp文件中定义你的对象:
template <typename T> MyType const MyClass<T>::Type = some-initialization-here;
除非您在同一翻译单元中明确或隐式地实例化此定义,否则这将无效。您可以为特定类型定义成员,如下所示:
template <> MyType const MyClass<T>::Type = some-initialization-here;
除非你真的需要这个类型是一个常量表达式,在这种情况下你通常可以侧面解决问题,如果有必要的话,可以使它成为enum
(这是我倾向于做的,因为这个人可以是绑定到const
引用而不需要定义),您可以使用静态成员函数,该函数可以在头文件中定义:
template <typename T>
MyType const& MyClass<T>::Type() {
static MyType rc = some-initialization-here;
return rc;
}
顺便说一句,我很确定这个问题之前得到了解答,绝对是comp.lang.c++.moderated。
答案 1 :(得分:1)
在标题内初始化类型将导致多次初始化。
嗯,当然。对于MyClass
实例化的每种不同类型的一次。它也是每种类型的不同对象,这是模板工作的固有特性。如果您只想定义和初始化一次,请将其放在非模板库中:
namespace detail{
class MyClassBase{
protected:
~MyClassBase(){} // only usable as a base class, non-polymorphic
static const MyType Type; // only available to derived types
};
} // detail::
template<class T>
class MyClass
: private detail::MyClassBase // private, non-polymorphic
{
public:
using MyClassBase::Type; // if you want to expose 'Type' to the public audience
};
现在你可以放
const MyType detail::MyClassBase::Type = /*initialize here*/;
在.cpp中完成。
请注意,将static
对象封装在函数中通常会更好,正如@Dietmar所示。这些函数局部静态优于任何其他类型的静态对象,因为在使用它们时不会遇到静态初始化顺序fiasco。