在运行时可以检测到C ++ 03和C ++ 11之间有什么区别?
可以编写一个函数,当使用C编译器编译时,它将返回0,当使用C ++编译器编译时,函数将返回1(使用#ifdef __cplusplus
的平凡的#ifdef __cplusplus
不是很有趣)。
例如:
int isCPP() { return sizeof(char) == sizeof 'c'; }
当然,只有当sizeof (char)
和sizeof (int)
不一样时,
另一个更便携的解决scheme是这样的:
int isCPP() { typedef int T; { struct T { int a[2]; }; return sizeof(T) == sizeof(struct T); } }
我不确定这些例子是否100%正确,但是你明白了。 我相信还有其他的方法来编写相同的function。
在运行时可以检测到C ++ 03和C ++ 11之间有什么区别? 换句话说,是否有可能编写一个类似的函数,它会返回一个布尔值,表示它是否由符合的C ++ 03编译器或C ++ 11编译器编译?
bool isCpp11() { //??? }
核心语言
使用::
访问一个枚举器:
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); }
您也可以滥用新的关键字
struct a { }; struct b { a a1, a2; }; struct c : a { static b constexpr (a()); }; bool isCpp0x() { return (sizeof c::a()) == sizeof(b); }
此外,string文字不再转换为char*
bool isCpp0xImpl(...) { return true; } bool isCpp0xImpl(char*) { return false; } bool isCpp0x() { return isCpp0xImpl(""); }
我不知道你有多大的可能性,但是这个工作在真正的实现上。 一个利用auto
struct x { x(int z = 0):z(z) { } int z; } y(1); bool isCpp0x() { auto x(y); return (yz == 1); }
以下是基于这样一个事实,即operator int&&
是在C ++ 0x中转换为int&&
函数,并且转换为int
然后是逻辑和在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); }
该testing用例在GCC中不适用于C ++ 0x(看起来像一个bug),并不适用于铿锵的C ++ 03模式。 一个叮当公关已经提交 。
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(); }
可以使用几个“检测这是C ++ 03还是C ++ 0x”来演示重大更改。 以下是一个经过调整的testing用例,最初用来演示这样的变化,但现在用于testingC ++ 0x或C ++ 03。
struct X { }; struct Y { X x1, x2; }; struct A { static XB(int); }; typedef AB; struct C : A { using ::B::B; // (inheriting constructor in c++0x) static YB(...); }; bool isCpp0x() { return (sizeof C::B(0)) == sizeof(Y); }
标准库
在C ++ 0x'std std::basic_ios
检测到operator void*
的缺失
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); }
我从C ++ 11中引入了什么突破性的变化中得到了启发? :
#define u8 "abc" bool isCpp0x() { const std::string s = u8"def"; // Previously "abcdef", now "def" return s == "def"; }
这是基于优先于macros扩展的新string文字。
如何检查使用新的规则>>
闭幕模板:
#include <iostream> const unsigned reallyIsCpp0x=1; const unsigned isNotCpp0x=0; template<unsigned> struct isCpp0xImpl2 { typedef unsigned isNotCpp0x; }; template<typename> struct isCpp0xImpl { static unsigned const reallyIsCpp0x=0x8000; static unsigned const isNotCpp0x=0; }; bool isCpp0x() { unsigned const dummy=0x8000; return isCpp0xImpl<isCpp0xImpl2<dummy>>::reallyIsCpp0x > ::isNotCpp0x>::isNotCpp0x; } int main() { std::cout<<isCpp0x()<<std::endl; }
或者快速检查std::move
:
struct any { template<typename T> any(T const&) {} }; int move(any) { return 42; } bool is_int(int const&) { return true; } bool is_int(any) { return false; } bool isCpp0x() { std::vector<int> v; return !is_int(move(v)); }
与以前的C ++不同,C ++ 0x允许通过引用types创build引用types,例如,通过模板参数引入基础引用types:
template <class T> bool func(T&) {return true; } template <class T> bool func(...){return false;} bool isCpp0x() { int v = 1; return func<int&>(v); }
不幸的是,完美的转发是以向后兼容性为代价的。
另一个testing可以基于现在允许的本地types作为模板参数:
template <class T> bool cpp0X(T) {return true;} //cannot be called with local types in C++03 bool cpp0X(...){return false;} bool isCpp0x() { struct local {} var; return cpp0X(var); }
这不是一个正确的例子,但它是一个有趣的例子,可以区分C和C ++ 0x(虽然它是无效的C ++ 03):
int IsCxx03() { auto x = (int *)0; return ((int)(x+1) != 1); }
从这个问题来看:
struct T { bool flag; T() : flag(false) {} T(const T&) : flag(true) {} }; std::vector<T> test(1); bool is_cpp0x = !test[0].flag;
虽然不那么简洁…在当前的C ++中,类模板名称本身在该类模板的作用域中被解释为types名称(不是模板名称)。 另一方面,类模板名称可以用作C ++ 0x(N3290 14.6.1 / 1)中的模板名称。
template< template< class > class > char f( int ); template< class > char (&f(...))[2]; template< class > class A { char i[ sizeof f< A >(0) ]; }; bool isCpp0x() { return sizeof( A<int> ) == 1; }
#include <utility> template<typename T> void test(T t) { t.first = false; } bool isCpp0x() { bool b = true; test( std::make_pair<bool&>(b, 0) ); return b; }