C++ g+中的模板规范编译错误+;
我有一个模板化的容器对象。我试图为C++ g+中的模板规范编译错误+;,c++,templates,compiler-errors,C++,Templates,Compiler Errors,我有一个模板化的容器对象。我试图为float版本创建一个专门的构造函数。问题是,当编译器试图编译使用float版本的第二个对象时,我得到了一个错误的多重定义 注意:整个类在h文件中。该文件用定义(#ifndef、#define和#endif)包装。g++版本3.4.6。这可以与其他编译器(如英特尔的icc)进行良好的编译 代码类似于以下内容: template <typename T> class Container { public: Container(); virt
float
版本创建一个专门的构造函数。问题是,当编译器试图编译使用float
版本的第二个对象时,我得到了一个错误的多重定义
注意:整个类在h
文件中。该文件用定义(#ifndef
、#define
和#endif
)包装。g++版本3.4.6。这可以与其他编译器(如英特尔的icc)进行良好的编译
代码类似于以下内容:
template <typename T>
class Container {
public:
Container();
virtual ~Container() {}
private:
std::vector<T> data;
// other members
};
template <> Container<float>::Container() {
// do something special
}
template <typename T> Container<T>::Container() {
// do default initialization
}
模板
类容器{
公众:
容器();
虚拟~Container(){}
私人:
std::矢量数据;
//其他成员
};
模板容器::容器(){
//做点特别的事
}
模板容器::容器(){
//执行默认初始化
}
有什么想法吗?谢谢
编辑正在编译的对象也将进入单独的共享对象,不确定这是否与此有关。您可以使用typeid
:
template <typename T> Container<T>::Container() {
if(typeid(T)==typeid(float)) {
// do something special
}
else {
// do default initialization
}
}
模板容器::容器(){
if(typeid(T)=typeid(float)){
//做点特别的事
}
否则{
//执行默认初始化
}
}
缺点:您不能将初始化列表用于特殊情况。
编辑:
当我写下这个答案时,我仍然认为错误是由编译器引起的,而不是由OP的代码引起的(没有深入研究它)。但是,这个Type ID方法绝对有效C++(见下面的链接),如果模板确实不能用你的特定编译器正确工作,那么它是一个相当好的解决方法,如果你能切换到更好的编译器,它很容易被模板解决方案取代。
演示:模板容器::容器(){
//做点特别的事
}
是专业化的定义。专业化必须在使用的每个编译单元中声明:
template <> Container<float>::Container();
模板容器::容器();
仅在CU的一个中定义。因此,您的.h
必须具有声明,并且您必须为定义找到适当的(可能是新的).cpp
。(正如Mark B所指出的,将专门化内联也是一种允许将定义放在所有需要的编译单元中的方法)。专门化仍然必须遵守一个定义规则,就像其他任何非模板方法一样。要么内联标记它,要么在源文件(而不是头文件)中定义方法体。这很棘手。问题是你的专业不是一个好的选择
模板,但实际的函数定义。既然它是在一个
头,当您包含它两次时,会得到多个定义。
比如:
template<> Container<float>::Container();
模板容器::容器();
在头文件中,在单个源文件中实现。g++4.0.1也可以。升级?目前,我无法升级,或者相信我,我会升级。我被锁定在这个应用程序的版本中。只是为了测试,我将代码复制到一个有g++4.1.1的框中,并得到了相同的错误。这不是很糟糕的设计吗?因为这种尝试抛弃了模板提供的所有可能性。@tgmath:i aggree,最常用的代码是使用typeid
表示糟糕的设计。但是在这种情况下,给定给typeid
的参数是一个类型而不是一个对象,这并没有那么糟糕。当然,如果可能的话,应该使用你的模板。@f4:不,我不这么认为。请参阅我的链接。@smerlin如果一个操作对float类型有效,而对其他T类型无效,则会出现编译错误。这可以通过模板专门化来避免。
template<> Container<float>::Container();