这适用于 GCC 4.7 和 4.8,正确地告诉我是否提供了旧特性或新特性:
#include <type_traits>
namespace std
{
template<typename> struct has_trivial_destructor;
template<typename> struct is_trivially_destructible;
}
template<typename T>
class have_cxx11_trait_helper
{
template<typename T2, bool = std::is_trivially_destructible<T2>::type::value>
static std::true_type test(int);
template<typename T2, bool = std::has_trivial_destructor<T2>::type::value>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) type;
};
template<typename T>
struct have_cxx11_trait : have_cxx11_trait_helper<T>::type
{ };
int main()
{
static_assert( have_cxx11_trait<int>::value, "new trait" );
}
注意我声明(但不定义)这两个特征,因为标准库(可能)不会声明两者,如果甚至没有声明名称,那么你就不能引用std::is_trivially_destructible
. 所以我将它们都声明了,但只有库定义的一个可以使用。向命名空间添加声明在std
技术上是未定义的行为,因此使用它需要您自担风险(尽管在这种情况下不太可能擦除您的硬盘。)
不幸的是,不提供新特性的旧编译器也可能无法处理代码——我没有检查它是否适用于 GCC 4.6
现在您可以定义自己的可移植特征:
template<typename T>
using is_trivially_destructible
= typename std::conditional<have_cxx11_trait<T>::value,
std::is_trivially_destructible<T>,
std::has_trivial_destructor<T>>::type;
的语义has_trivial_destructor
与新特性不同,但对于不支持新特性的旧编译器来说,这是一个合理的近似值。
或者,您可以使用静态多态性根据可用的类型特征来获取不同的代码,例如通过专门化模板或通过重载和标签调度,如下所示:
template<typename T>
void foo_helper(const T&, std::true_type)
{
// code that uses std::is_trivially_destructible
}
template<typename T>
void foo_helper(const T&, std::false_type)
{
// different code using std::has_trivial_destructor
}
template<typename T>
void foo(const T& t)
{
// do common stuff
// stuff that depends on trait
foo_helper(t, has_cxx11_trait<T>{});
// more common stuff
}
在制作这个答案时没有损害宏。