什么区别,如果有的话,C ++ 03和C ++ 11之间可以在运行时被检测到?什么区别,如果有的话,

2019-05-12 20:19发布

是可能的写的函数,其中,当与C编译器编译将返回0,并且当与C ++编译器编译的,将返回1(与琐碎sulution #ifdef __cplusplus不感兴趣)。

例如:

int isCPP()
{
    return sizeof(char) == sizeof 'c';
}

当然,上述只会工作,如果sizeof (char)是不一样sizeof (int)

另外,更便携的解决方案是这样的:

int isCPP()
{
    typedef int T;
    {
       struct T 
       {
           int a[2];
       };
       return sizeof(T) == sizeof(struct T);
    }
}

我不知道,如果例子是100%正确的,但你的想法。 我相信还有其他方法来写同样的功能了。

什么区别,如果有的话,C ++ 03和C ++ 11之间可以在运行时被检测到? 换句话说,是有可能写一个类似功能,其将返回指示是否它是由一个符合C ++编译器03编译或一个C ++编译器11的布尔值?

bool isCpp11()
{ 
    //???
} 

Answer 1:

核心语言

访问使用枚举::

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);
}

而且,事实上,字符串字面不要再转换为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 (y.z == 1);
}

是基于这样的事实,下面的operator int&&是转换函数来int&& C ++ 0x中,和转换到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);
}

那测试用例不适合的C ++ 0x在GCC工作(看起来像一个bug)和铛不起作用在C ++ 03模式。 一个铛PR已经提交 。

该改性处理注入的类名的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”可以用来表明重大更改。 下面是一个微调的测试用例,最初用于证明这样的改变,但现在被用于测试的C ++ 0x或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); }

标准库

检测缺乏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);
}


Answer 2:

我从一个灵感是什么重大的变动在C ++ 11引入?

#define u8 "abc"

bool isCpp0x() {
   const std::string s = u8"def"; // Previously "abcdef", now "def"
   return s == "def";
}

这是基于优先于宏展开新的字符串文字。



Answer 3:

如何使用新规则的检查>>收盘模板:

#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));
}


Answer 4:

从参考类型创建不同于现有C ++,C ++ 0X允许引用类型如果该基本参考类型是通过引入,例如,一个模板参数:

template <class T> bool func(T&) {return true; } 
template <class T> bool func(...){return false;} 

bool isCpp0x() 
{
    int v = 1;
    return func<int&>(v); 
}

完美转发来打破向后兼容性,可惜的价格。

另一个测试可以立足现在,让本地类型作为模板参数:

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);
}


Answer 5:

这是不太正确的例子,但它是可以区分一个有趣的例子C对的C ++ 0x(这是无效的C ++ 03虽然):

 int IsCxx03()
 {
   auto x = (int *)0;
   return ((int)(x+1) != 1);
}


Answer 6:

从这个问题 :

struct T
{
    bool flag;
    T() : flag(false) {}
    T(const T&) : flag(true) {}
};

std::vector<T> test(1);
bool is_cpp0x = !test[0].flag;


Answer 7:

虽然不是那么简洁......在当前的C ++,类模板名称本身被解释为在类模板的作用域类型名称(不是一个模板名称)。 在另一方面,类模板名称可以用作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;
}


Answer 8:

#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;
}


文章来源: What differences, if any, between C++03 and C++11 can be detected at run-time?