2017-04-14 63 views
1

静态成员的我一直读到你可以定义一个特质像初始化的特质

enum MyEnum { val_1, val_2, val_3 }; 

template< typename T > 
struct my_trait { 
    static const MyEnum value = MyEnum::val_1; 
}; 

,然后专门它

template<> 
struct my_trait <void>{ 
    static const MyEnum value = val_3; 
}; 

当我尝试它,我总是得到一个链接错误,因为static成员没有定义,所以我必须明确地将其专门化为源文件

MyEnum my_trait <void>::value = val_3; 

和更改在标题中

template<> 
struct is_void<void>{ 
    static const MyEnum value; 
}; 

是否有任何方式直接在报头中定义的特征的定义而不必重新定义它在头?

+0

它没有被定义ODR使用。 AFAICR,你不应该使用标准的':: value'。 – chris

+0

你的意思是“一个定义规则” - 用什么? – Lezkus

+0

@Lezkus“odr-used”是标准中的一个术语。撇开细微差别,它意味着“物体本身而不是价值被使用”。如绑定到参考或采取其地址。 – Angew

回答

0

不完全是你的问题的答案,但在你的例子中(如果你可以使用C++ 11 compliler),你可以使用std::integral_constant

完整的例子

#include <iostream> 
#include <type_traits> 

enum MyEnum { val_1, val_2, val_3 }; 

template< typename T > 
struct my_trait : public std::integral_constant<MyEnum, MyEnum::val_1> 
{ }; 

template<> 
struct my_trait<void> : public std::integral_constant<MyEnum, MyEnum::val_3> 
{ }; 

int main() 
{ 
    std::cout << my_trait<void>::value << std::endl; // print 2 (aka val_3) 
    std::cout << my_trait<int>::value << std::endl; // print 0 (aka val_1) 
} 
+0

我刚才举了一个例子。我正在使用的真实代码稍微复杂一点。 – Lezkus

+1

@Lezkus - 我明白了......呃,我想你应该提出一个小例子,展示如何得到错误 – max66

+0

我编辑了实际用例的问题。我虽然认为其他任何类型的公式都是相同的,但显然并非如此。 – Lezkus

0

这将导致链接错误:

std::cout << &is_void<void>::value << std::endl; 

因为你ODR使用value - 这意味着你需要它的地址。我不确定,但是这也可能在引用时发生 - 因为它们可能是作为指针在内部实现的。所以,直到C++ 14,你将不得不定义你的value里面的实现文件。

由于C++ 17,你可以使用内联变量来保持它在一个地方,即使你需要ODR使用它:如果它不

template< typename T > 
struct is_void{ 
    inline static const bool value = false; 
    ^^^^^^ 
};