【问题标题】:avoiding multiply-defined symbols when specializing a templatized static const member在特化模板化静态 const 成员时避免多重定义的符号
【发布时间】:2014-02-28 06:53:45
【问题描述】:

我遇到的问题与此处讨论的主题非常相似: How to properly specialize a templatized static const member that is the same type as its parent

这是我的代码:

template <class T>
class p3d
{
public:
    p3d() {
        x = 0;
    }

    p3d(const T &_x) {
        x = _x;
    }

    static const p3d<T> origin;

    T x;
};

typedef p3d<float> p3df;

int main(int, char**)
{
    p3df p = p3df::origin;
    return 0;
}

// elsewhere in a *.cpp file
template<> const p3df p3df::origin(0.0f);

在 Clang 等严格的编译器下编译时,出现以下错误:

explicit specialization of 'origin' after instantiation
template<> const p3df p3df::origin(0.0f); -> implicit instantiation first required here

解决办法是移动

template<> const p3df p3df::origin(0.0f);

在 typedef 之前。这个解决方案的问题在于它会导致多重定义的符号,因为现在p3df::origin 在每个使用矢量头的文件中都定义了。有什么方法可以正确专门化静态 const typedef-ed 模板,同时避免使用 typedef 在所有源文件中重复定义?

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    移动线

    template<> const p3df p3df::origin(0.0f);
    

    main() 函数之前,但在typedef 之后。

    我真的不确定这里有什么问题。似乎 clang 抱怨您使用所述专业化之后 为模板专业化提供了定义。 gcc/4.9 (nightly build) 没有问题。

    一般来说,在头文件中定义静态模板很酷,因为它们——顾名思义——是模板。但是,如果您专门化您的模板,从而使其成为一个实际的类,则一个定义规则适用于任何常规类,您需要将定义移动到非头文件中。

    【讨论】:

    • 我同意当代码全部位于一个文件中时,提前移动模板是可行的。但是因为会有多个源文件,包括 p3d 类的头文件,这也意味着会有多个“template const p3df p3df::origin(0.0f);”的实例,并且在链接时,Clang(和大多数其他编译器)将由于多重定义的符号而失败。
    猜你喜欢
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多