1. ホーム
  2. c++

[解決済み] C++03とC++11の違いを実行時に検出できるとすれば、それはどのようなものですか?

2022-10-05 12:05:36

質問

Cコンパイラでコンパイルすると0を返し、C++コンパイラでコンパイルすると1を返す関数を書くことができます(些細な計算で #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()
{ 
    //???
} 

どのように解決するのですか?

コア言語

列挙子へのアクセスは :: :

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

そのテストケースはGCCのC++0xでは動作せず(バグのようです)、clangのC++03モードでは動作しません。 clang の PR が提出されました。 .

この は注入されたクラス名の扱いを変更しました。 の扱いが変更されました。

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