This works for me with GCC 4.7 and 4.8, correctly telling me whether the old or new trait is provided:
#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" );
}
N.B. I declare (but don't define) both traits because the standard library (probably) won't declare both and if the name isn't even declared then you can't refer to std::is_trivially_destructible
. So I declare them both, but only the one defined by the library will be usable. Adding declarations to namespace std
is technically undefined behaviour, so use it at your own risk (it's not likely to wipe your hard drive in this case though.)
Unfortunately an older compiler that doesn't provide the new trait might not be able to handle the code either -- I haven't checked if it works with GCC 4.6
Now you can define your own portable trait:
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;
The semantics of has_trivial_destructor
aren't the same as the new trait, but it's a reasonable approximation for older compilers that don't support the new trait.
Alternatively, you could use static polymoprhism to get different code depending on which type trait is available, e.g. by specializing templates or by overloading and tag dispatching, like so:
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
}
No macros were harmed in the making of this answer.
__GNUC_MINOR__
might make it a little easier. – Escargot