रन-टाइम में C ++ 03 और C ++ 11 के बीच क्या अंतर है, यदि कोई है, तो पता लगाया जा सकता है?


116

एक फ़ंक्शन लिखना संभव है, जो, जब एक सी कंपाइलर के साथ संकलित 0 वापस आएगा, और जब एक सी ++ कंपाइलर के साथ संकलित किया जाएगा, तो 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()
{ 
    //???
} 

10
और इस अभ्यास का क्या मतलब है? सबसे पहले, आपके पास एक मैक्रो है, और दूसरी बात यह है कि कंपाइलरों को C ++ 0x की सभी विशेषताओं को लागू करने से पहले कई साल लगेंगे, इस बीच यह एक मिश्रण होगा। तो केवल उचित परीक्षण संकलक एक संस्करण मैक्रो है।
जीन बुश्यूयेव

4
यह एक वास्तविक सवाल नहीं है, लेकिन नियमों का पालन करना बहुत दिलचस्प लगता है!
डेविड हेफर्नन

4
@ गेन एट अल: क्या आप उन सभी सवालों को दरकिनार कर देते हैं जो दिलचस्प हैं लेकिन आप व्यावहारिक "बिंदु" नहीं देखते हैं?
आर्मेन त्सिरुयन

2
"हम आम तौर पर तथ्यों, संदर्भों या विशिष्ट विशेषज्ञता को शामिल करने के उत्तर की उम्मीद करते हैं"। मुझे लगता है कि यह सवाल इन उम्मीदों को पूरा करता है, फिर से वोट करें।
कारेल पेट्रानेक

6
@sixlettervariables: हालांकि यह निश्चित रूप से इस तर्क के लिए खुला है कि रिट्रासिंग बेहतर हो सकती है, यह मुझे लगता है कि प्रश्न की मौलिक धारणा (क्या अंतर है, यदि कोई है, तो C ++ 03 और C ++ 0x के बीच रन-वे पर पता लगाया जा सकता है) समय?) पूरी तरह से वैध है। यह देखते हुए कि कोड को दोनों में संकलित और निष्पादित करना है, इसे C ++ 0x में ब्रेकिंग परिवर्तन के बारे में बताया जा सकता है। यह मेरे लिए भी एक पूरी तरह से वैध सवाल पूछने के लिए लगता है।
जेरी कॉफिन

जवाबों:


108

कोर भाषा

एक एन्यूमरेटर का उपयोग करना :::

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

निम्नलिखित इस तथ्य पर आधारित है कि 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);
}

वह परीक्षण-मामला GCC में C ++ 0x के लिए काम नहीं करता है (बग जैसा दिखता है) और clang के लिए C ++ 03 मोड में काम नहीं करता है। एक क्लेंग पीआर दायर किया गया है

इंजेक्शन वर्ग नामों में से संशोधित उपचार सी ++ 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();
}

"यह पता लगाना कि यह 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);
}

1
अच्छा लगा। मैं पुष्टि कर सकता हूं कि यह समाधान g ++ (GCC) 4.6.0 के साथ काम करता है, दोनों के साथ और बिना -std = c ++ 0x।
अलेक्जेंडर

2
यह trueएमएसवीसी 2005 के लिए रिटर्न , और एमएसवीसी 2003 में एक संकलन त्रुटि है।
एंथनी विलियम्स

1
ओह प्रिय, उन्होंने पीछे की संगतता को तोड़ दिया!
अवकर

14
@ जोहान्स: यह सबसे मजेदार है जो आपने हफ्तों में किया है, है ना? ; -]
ildjarn

4
मुझे यह सब बहुत दिलचस्प लगता है, लेकिन मुझे लगता है कि सबसे चतुर (...)बनाम (char*)कॉल है। वह सहीं मे मुझे पसन्द है!
corsiKa

44

मुझे एक प्रेरणा मिली कि C ++ 11 में कौन से ब्रेकिंग परिवर्तन पेश किए गए हैं? :

#define u8 "abc"

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

यह नए स्ट्रिंग शाब्दिक पर आधारित है जो वृहद विस्तार पर पूर्वता लेता है।


1
+1: बहुत दिलचस्प, वास्तव में, लेकिन तकनीकी रूप से प्रीप्रोसेसर का उपयोग न करने की आवश्यकता को तोड़ता है। लेकिन इस तरह के अच्छे जवाबों को खारिज करने का इरादा नहीं था :)
आर्मेन त्सिरुएनन 20

1
ठीक है, यदि आप फ़ंक्शन का अनुसरण करते हैं #undef u8तो प्रीप्रोसेसर का उपयोग केवल तभी संभव है जब आपके प्रोग्राम में पहले से परिभाषित मैक्रो u8(boooo) नाम हो । यदि यह एक वास्तविक चिंता है, तो इसे अभी भी कार्यान्वयन-विशिष्ट पुश / पॉप मैक्रो प्रैग्मस / कॉल का उपयोग करके काम किया जा सकता है (अधिकांश कार्यान्वयन में ये हैं, मुझे विश्वास है)।
जेम्स मैकनेलिस

3
एक उचित तर्क यह है कि C ++ 03 सिस्टम पर कोई व्यक्ति #define u8 को नकली C ++ 0x क्षमताएं प्रदान कर सकता है। फिर भी, मुझे जवाब पसंद है।
क्रिस्टोफर स्मिथ

1
आप बस इसे स्थानांतरित कर सकते हैं .Cpp0x फ़ंक्शन को एक अलग अनुवाद इकाई में स्थानांतरित करें ताकि यह मैक्रो चीज़ अन्य कोड को प्रभावित न करे।
अनकूलुंकुलु

1
मुझे लगता है कि संकलक पर कुछ मैक्रो मान सेट करने के लिए प्रीप्रोसेसर का उपयोग करने और वास्तविक भाषा सुविधाओं का पता लगाने के लिए प्रीप्रोसेसर का उपयोग करने के बीच अंतर है। इसलिए मुझे नहीं लगता कि यह जवाब धोखा है।
ऑर्बिट

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

वैकल्पिक रूप से इसके लिए एक त्वरित जांच 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));
}

6
+1 वास्तव में एक अच्छा विचार :) हालांकि, व्यवहार में यह दृश्य C ++ 2005/2088 के साथ टूट जाएगा जो C ++ 0x का समर्थन नहीं करते हैं, लेकिन >> को C ++ 0x तरीके से उपयोग करने की अनुमति देते हैं।
कारेल पेट्रानेक

4
ओह, मुझे ADL दुरुपयोग पसंद है! हालाँकि, एक अनुरूप C ++ 03 कार्यान्वयन एक समारोह नाम नहीं है std::move?
जेम्स मैकनेलिस

1
@FredOverflow: मैं परेशान नहीं होता। यूआई बेकार है!
ऑर्बिट में लाइटनेस दौड़

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

सही अग्रेषण दुर्भाग्य से, पीछे की ओर संगतता को तोड़ने की कीमत पर आता है।

एक अन्य परीक्षण अब स्थानीय तर्क-आधारित तर्कों के आधार पर किया जा सकता है:

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

शायद मुझे इसे एक विशेषता वर्ग में बदल देना चाहिए;)
uwedolinsky

1
+1 अच्छा विचार, मुझे यकीन नहीं है कि अगर isC++0xएक वैध सी ++ पहचानकर्ता है;)
कारेल पेट्रानेक

1
संदर्भ के संदर्भ से संदर्भ के लिए एक अच्छा संदर्भ क्या है?
केरेक एसबी

@ kerrek-sb: मसौदा इस बारे में 8.3.2.6 में बात करता है (संदर्भ)
uwedolinsky

15

यह काफी सही उदाहरण नहीं है, लेकिन यह एक दिलचस्प उदाहरण है जो C बनाम C ++ 0x को अलग कर सकता है (हालांकि यह अमान्य C ++ 03 है):

 int IsCxx03()
 {
   auto x = (int *)0;
   return ((int)(x+1) != 1);
}

10
तकनीकी रूप से, यह sizeof(int) != 1सच होने पर निर्भर करता है। असाधारण बड़े charएस के साथ एक 0x प्रणाली पर , परिणाम समान हो सकते हैं। फिर भी एक साफ सुथरी चाल।
डेनिस ज़िकफ़ोज़

@ डेनिस - charहमेशा एक बाइट है हालांकि
नोड

4
@ नोड: एक बाइट हमेशा 8 बिट नहीं होती है।
अलेक्जेंड्रे सी।

2
@ नोड sizeof(char)हमेशा 1 होगा, परिभाषा के अनुसार। लेकिन CHAR_BIT(limits.h में परिभाषित) की तुलना में अधिक 8. नतीजतन होने की अनुमति दी है, दोनों charऔर int32 बिट, जिस स्थिति में हो सकता है sizeof(int) == 1(और CHAR_BIT == 32)।
Sjoerd

12

से इस सवाल :

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

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

मैंने सोचा कि यह कैसे काम कर सकता है; यह कोशिश कर रहा है, यह अब स्पष्ट है: थोड़ा बग है। यदि आप अंतिम पंक्ति को बदलते हैं तो यह काम करता है:bool is_cpp0x = !test[0].flag;
awx

1
प्रशंसनीय: C ++ 0x डिफ़ॉल्ट निर्माण Tजबकि C ++ 03 प्रतिलिपि निर्माणT()
awx

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

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

NB तकनीकी रूप से यह मानक लाइब्रेरी का परीक्षण करता है न कि संकलक का, और यद्यपि यह मान्य C ++ 03 और वैध C ++ 0x है, यह C ++ 98 मान्य नहीं है, इसलिए C ++ 98 / का पता लगाने के लिए कुछ ट्विक के साथ बनाया जा सकता है। C ++ 03 / C ++ 0x stdlib
जोनाथन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.