[英]What differences, if any, between C++03 and C++11 can be detected at run-time?
可以編寫一個函數,當用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(看起來像一個bug),並且在C ++ 03模式下不能用於clang。 已經提交了一個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); }
檢測C ++ 0xstd 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";
}
這基於新的字符串文字,它優先於宏擴展。
如何使用>>
關閉模板的新規則進行檢查:
#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允許從引用類型創建引用類型:
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);
}
這不是一個正確的例子,但它是一個有趣的例子,可以區分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 ++中,類模板名稱本身被解釋為該類模板范圍內的類型名稱(而不是模板名稱)。 另一方面,類模板名稱可以用作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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.