It is possible to write a function, which, when compiled with a C compiler will return 0, and when compiled with a C++ compiler, will return 1 (the trivial sulution with
This isn't quite a correct example, but it's an interesting example that can distinguish C vs. C++0x (it's invalid C++03 though):
int IsCxx03()
{
auto x = (int *)0;
return ((int)(x+1) != 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;
}
Though not so concise... In current C++, class template name itself is interpreted as a type name (not a template name) in that class template's scope. On the other hand, class template name can be used as a template name in 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;
}
I got an inspiration from What breaking changes are introduced in C++11?:
#define u8 "abc"
bool isCpp0x() {
const std::string s = u8"def"; // Previously "abcdef", now "def"
return s == "def";
}
This is based on the new string literals that take precedence over macro expansion.
Unlike prior C++, C++0x allows reference types to be created from reference types if that base reference type is introduced through, for example, a template parameter:
template <class T> bool func(T&) {return true; }
template <class T> bool func(...){return false;}
bool isCpp0x()
{
int v = 1;
return func<int&>(v);
}
Perfect forwarding comes at the price of breaking backwards compatibility, unfortunately.
Another test could be based on now-allowed local types as template arguments:
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);
}
From this question:
struct T
{
bool flag;
T() : flag(false) {}
T(const T&) : flag(true) {}
};
std::vector<T> test(1);
bool is_cpp0x = !test[0].flag;