What differences, if any, between C++03 and C++11 can be detected at run-time?

后端 未结 8 1405
深忆病人
深忆病人 2020-12-02 04:44

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

相关标签:
8条回答
  • 2020-12-02 05:15

    Core Language

    Accessing an enumerator using :::

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

    You can also abuse the new keywords

    struct a { };
    struct b { a a1, a2; };
    
    struct c : a {
      static b constexpr (a());
    };
    
    bool isCpp0x() {
      return (sizeof c::a()) == sizeof(b);
    }
    

    Also, the fact that string literals do not anymore convert to char*

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

    I don't know how likely you are to have this working on a real implementation though. One that exploits auto

    struct x { x(int z = 0):z(z) { } int z; } y(1);
    
    bool isCpp0x() {
      auto x(y);
      return (y.z == 1);
    }
    

    The following is based on the fact that operator int&& is a conversion function to int&& in C++0x, and a conversion to int followed by logical-and in 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);
    }
    

    That test-case doesn't work for C++0x in GCC (looks like a bug) and doesn't work in C++03 mode for clang. A clang PR has been filed.

    The modified treatment of injected class names of templates in 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();
    }
    

    A couple of "detect whether this is C++03 or C++0x" can be used to demonstrate breaking changes. The following is a tweaked testcase, which initially was used to demonstrate such a change, but now is used to test for C++0x or 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); }
    

    Standard Library

    Detecting the lack of operator void* in 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);
    }
    
    0 讨论(0)
  • 2020-12-02 05:15

    How about a check using the new rules for >> closing templates:

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

    Alternatively a quick check for 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));
    }
    
    0 讨论(0)
提交回复
热议问题