Langue de base
Accéder à un énumérateur en utilisant ::
:
template<int> struct int_ { };
template<typename T> bool isCpp0xImpl(int_<T::X>*) { return true; }
template<typename T> bool isCpp0xImpl(...) { return false; }
enum A { X };
bool isCpp0x() {
return isCpp0xImpl<A>(0);
}
Vous pouvez également abuser des nouveaux mots clés
struct a { };
struct b { a a1, a2; };
struct c : a {
static b constexpr (a());
};
bool isCpp0x() {
return (sizeof c::a()) == sizeof(b);
}
De plus, le fait que les littéraux de chaîne ne se convertissent plus en char*
bool isCpp0xImpl(...) { return true; }
bool isCpp0xImpl(char*) { return false; }
bool isCpp0x() { return isCpp0xImpl(""); }
Je ne sais pas dans quelle mesure vous avez des chances que cela fonctionne sur une implémentation réelle. Celui qui exploiteauto
struct x { x(int z = 0):z(z) { } int z; } y(1);
bool isCpp0x() {
auto x(y);
return (y.z == 1);
}
Ce qui suit est basé sur le fait qu'il operator int&&
s'agit d'une fonction de conversion int&&
en C ++ 0x, et d'une conversion en int
suivi de logique et en C ++ 03
struct Y { bool x1, x2; };
struct A {
operator int();
template<typename T> operator T();
bool operator+();
} a;
Y operator+(bool, A);
bool isCpp0x() {
return sizeof(&A::operator int&& +a) == sizeof(Y);
}
Ce cas de test ne fonctionne pas pour C ++ 0x dans GCC (ressemble à un bogue) et ne fonctionne pas en mode C ++ 03 pour clang. Un clang PR a été déposé .
Le traitement modifié des noms de classe injectés des modèles en C ++ 11:
template<typename T>
bool g(long) { return false; }
template<template<typename> class>
bool g(int) { return true; }
template<typename T>
struct A {
static bool doIt() {
return g<A>(0);
}
};
bool isCpp0x() {
return A<void>::doIt();
}
Un couple de "détecter s'il s'agit de C ++ 03 ou C ++ 0x" peut être utilisé pour illustrer les changements de rupture. Ce qui suit est un cas de test modifié, qui a initialement été utilisé pour démontrer un tel changement, mais est maintenant utilisé pour tester C ++ 0x ou C ++ 03.
struct X { };
struct Y { X x1, x2; };
struct A { static X B(int); };
typedef A B;
struct C : A {
using ::B::B; // (inheriting constructor in c++0x)
static Y B(...);
};
bool isCpp0x() { return (sizeof C::B(0)) == sizeof(Y); }
Bibliothèque standard
Détecter le manque de operator void*
C ++ 0x 'std::basic_ios
struct E { E(std::ostream &) { } };
template<typename T>
bool isCpp0xImpl(E, T) { return true; }
bool isCpp0xImpl(void*, int) { return false; }
bool isCpp0x() {
return isCpp0xImpl(std::cout, 0);
}