任何人,请解释1)为什么下面的代码不适用于CLang 和 2)如何将其重写为与CLang兼容?
using LinkWeight = float;
template <bool WEIGHTED=true>
struct InpLink {
using Weight = LinkWeight; //!< \copydoc LinkWeight
Weight weight; //!< Link weight
// ...
};
template <>
struct InpLink<false> {
using Weight = LinkWeight; //!< \copydoc LinkWeight
constexpr static Weight weight = 1;
};
此代码在GCC上运行正常,但在Linux Ubuntu x64上的CLang 3.8.1上存在链接错误:
对“InpLink :: weight”的未定义引用
定义后:
template <>
constexpr typename InpLink<false>::Weight InpLink<false>::weight;
编译时错误是:extraneous 'template<>' in declaration of variable 'weight'
定义后:
template <bool WEIGHTED>
constexpr typename InpLink<false>::Weight InpLink<false>::weight;
编译时错误是:
..cluster.hpp:31:60: error: redefinition of 'weight' as different kind of symbol
constexpr typename InpLink<false>::Weight InpLink<false>::weight;
^
..cluster.h:58:27: note: previous definition is here
constexpr static Weight weight = 1;
这看起来像一个CLang的bug ...
注意:如果我在模板中有2个参数,执行部分特化并将静态constexpr权重定义为:,则相同的示例在CLang上正常工作
template <bool TMP>
constexpr typename InpLink<false, TMP>::Weight InpLink<false, UNSIGNED>::weight;
具有
template <bool WEIGHTED=true, bool TMP=true>
struct InpLink {
using Weight = LinkWeight; //!< \copydoc LinkWeight
Weight weight; //!< Link weight
// ...
};
template <bool TMP>
struct InpLink<false, TMP> {
using Weight = LinkWeight; //!< \copydoc LinkWeight
constexpr static Weight weight = 1;
};
显然我不想使用额外的模板参数来克服链接错误。还有其他方法可以解决这个问题吗? CLang 3.8.1或我的完整模板专业化有什么问题?
答案 0 :(得分:0)
因此,似乎这是CLang&lt; = 3.8.1中的一个错误,它限制了动态库中静态成员对constexpr的使用,并阻止了对完全专用模板的静态成员的单独定义。
克服它的方法是:
1.对CLang使用static const而不是constexpr
2.定义仅与模板声明相对应的静态成员,而不是完整的专业化:
template <bool WEIGHTED=false>
struct InpLink {
using Weight = LinkWeight; //!< \copydoc LinkWeight
//! Link is unweighted
constexpr static bool IS_WEIGHTED = false;
//! \copydoc SimpleLink<Weight>::weight
// ATTENTION: such complicated definition is required to overcome
// the linking error on CLang
#ifdef __clang__
const
#else
constexpr
#endif // __clang__
static Weight weight
#ifndef __clang__
= 1
#endif // !__clang__
;
// ...
};
template <>
struct InpLink<true> {
using Weight = LinkWeight; //!< \copydoc LinkWeight
Weight weight; //!< Link weight
// ...
};
并将.cpp中的静态权重定义为:
#ifdef __clang__
// Note: Required by CLang for the linking
template <>
const InpLink<false>::Weight InpLink<false>::weight = 1;
#endif // __clang__
对于发布版本来说,PS GCC实际上是一个比CLang更好,更可靠的编译器(CLang仍然有一些独特的调试优势)。