在运行时可以检测到C++ 03和C++ 11之间有什么区别?

Arm*_*yan 116 c++ language-detection c++11 c++03

可以编写一个函数,当用C编译器编译时它将返回0,并且当用C++编译器编译时,将返回1(微不足道的 #ifdef __cplusplus情况并不令人感兴趣).

例如:

int isCPP()
{
    return sizeof(char) == sizeof 'c';
}
Run Code Online (Sandbox Code Playgroud)

当然,只有在sizeof (char)不相同的情况下才会起作用sizeof (int)

另一个更便携的解决方案是这样的:

int isCPP()
{
    typedef int T;
    {
       struct T 
       {
           int a[2];
       };
       return sizeof(T) == sizeof(struct T);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定这些例子是否100%正确,但你明白了.我相信还有其他方法可以编写相同的功能.

在运行时可以检测到C++ 03和C++ 11之间有什么区别?换句话说,是否有可能编写一个类似的函数,它返回一个布尔值,表明它是由符合标准的C++ 03编译器还是C++ 11编译器编译的?

bool isCpp11()
{ 
    //???
} 
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 107

核心语言

使用::以下方式访问枚举器:

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);
}
Run Code Online (Sandbox Code Playgroud)

您也可以滥用新关键字

struct a { };
struct b { a a1, a2; };

struct c : a {
  static b constexpr (a());
};

bool isCpp0x() {
  return (sizeof c::a()) == sizeof(b);
}
Run Code Online (Sandbox Code Playgroud)

此外,字符串文字不再转换为 char*

bool isCpp0xImpl(...) { return true; }
bool isCpp0xImpl(char*) { return false; }

bool isCpp0x() { return isCpp0xImpl(""); }
Run Code Online (Sandbox Code Playgroud)

我不知道你有多大可能在真正的实现上工作.一个利用auto

struct x { x(int z = 0):z(z) { } int z; } y(1);

bool isCpp0x() {
  auto x(y);
  return (y.z == 1);
}
Run Code Online (Sandbox Code Playgroud)

以下是基于以下事实:在C++ 0x中operator int&&的转换函数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);
}
Run Code Online (Sandbox Code Playgroud)

该测试用例不适用于GCC中的C++ 0x(看起来像一个bug),并且在C++ 03模式下不能用于clang.已经提交了一个clang 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();
}
Run Code Online (Sandbox Code Playgroud)

一些"检测这是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); }
Run Code Online (Sandbox Code Playgroud)

标准图书馆

检测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);
}
Run Code Online (Sandbox Code Playgroud)

  • @Johannes:这是你几周来最开心的,不是吗?; - ] (14认同)
  • 圣洁的莫莉......!:-) (5认同)
  • 我发现这些都非常有趣,但我认为最聪明的是`(...)`vs`(char*)`调用.我真的很喜欢! (4认同)
  • 这将从MSVC 2005开始返回"true",在MSVC 2003中返回编译错误. (2认同)

Kar*_*nek 43

我从C++ 11中引入了哪些重大变化中获得灵感:

#define u8 "abc"

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

这基于新的字符串文字,它优先于宏扩展.

  • 一个相当合理的论点是,在C++ 03系统上,有人可能会#define u8来提供模拟的C++ 0x功能.不过,我真的很喜欢这个答案. (3认同)

Ant*_*ams 33

如何使用>>关闭模板的新规则进行检查:

#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;
}
Run Code Online (Sandbox Code Playgroud)

或者快速检查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));
}
Run Code Online (Sandbox Code Playgroud)

  • +1确实很酷的想法:)然而,在实践中,这将打破Visual C++ 2005/2088,它不支持C++ 0x但允许>>在模板中使用C++ 0x方式. (6认同)
  • 哦; 我喜欢滥用ADL!但是,一致的C++ 03实现是否有一个名为`std :: move`的函数? (4认同)

uwe*_*sky 16

与以前的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); 
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,完美转发是以破坏向后兼容性为代价的.

另一个测试可以基于现在允许的本地类型作为模板参数:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 非常好主意! (2认同)

Ada*_*eld 15

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

 int IsCxx03()
 {
   auto x = (int *)0;
   return ((int)(x+1) != 1);
}
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,这依赖于`sizeof(int)!= 1`为真.在具有特别大的`char`s的0x系统上,结果可能是相同的.不过还是一个巧妙的伎俩. (10认同)
  • @Node:一个字节不总是8位. (4认同)
  • 根据定义,@ Node`sizeof(char)`总是为1.但是`CHAR_BIT`(在limits.h中定义)允许大于8.结果,`char`和`int`都可以有32位,在这种情况下`sizeof(int)== 1`(和`CHAR_BIT == 32`). (2认同)

Ale*_* C. 12

这个问题:

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

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


Ise*_*ria 9

虽然不那么简洁......在当前的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;
}
Run Code Online (Sandbox Code Playgroud)


小智 9

#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;
}
Run Code Online (Sandbox Code Playgroud)