C ++ में सशर्त टाइपफेड कैसे बनाया जाए


89

मैं ऐसा कुछ करने की कोशिश कर रहा हूं:

#include <iostream>
#include <random>

typedef int Integer;

#if sizeof(Integer) <= 4
    typedef std::mt19937     Engine;
#else
    typedef std::mt19937_64  Engine;
#endif

int main()
{
    std::cout << sizeof(Integer) << std::endl;
    return 0;
}

लेकिन मुझे यह त्रुटि मिली:

error: missing binary operator before token "("

मैं सशर्त टाइपफ़ेड को सही ढंग से कैसे बना सकता हूं?


25
प्रीप्रोसेसर को sizeofC ++ के निर्माण के बारे में कुछ भी पता नहीं है । यह निश्चित रूप से आपके द्वारा बनाई गई चीजों के बारे में नहीं जानता है typedef, क्योंकि अभी तक इसे पार्स नहीं किया गया है।
ऑर्बिट

2
आप टाइपडिफ्स का उपयोग enable_ifया conditionalसशर्त रूप से परिभाषित कर सकते हैं, लेकिन आप उसके लिए प्रीप्रोसेसर का उपयोग नहीं कर सकते।
बार्टेक बैनचेविज़ जूल

1
@LightnessRacesinOrbit: प्रीप्रोसेसिंग और संकलन जीसीसी में एकीकृत हैं, इसलिए यह न केवल निश्चित है कि सॉफ्टवेयर प्रोसेसिंग कोड उपयोगकर्ता-निर्मित प्रकार की परिभाषाओं के बारे में नहीं जानता है, लेकिन जीसीसी के मामले में गलत माना जाता है। sizeofपूर्वप्रक्रमक स्थितियों में कारण काम नहीं कर सकता है क्योंकि भाषा को इस तरह परिभाषित किया गया है, न कि यह कि कार्यान्वयन कैसे काम करता है।
बजे एरिक पोस्टपिसिल

1
@LightnessRacesinOrbit: अनुवाद चरण वाक्यविन्यास और शब्दार्थ को परिभाषित करता है, प्रसंस्करण का क्रम नहीं। प्रति C ++ 2011 (N3092) 2.2 [lex.phases] नोट 11, "कार्यान्वयन को ऐसे व्यवहार करना चाहिए जैसे कि ये अलग-अलग चरण होते हैं, हालांकि व्यवहार में विभिन्न चरणों को एक साथ जोड़ दिया जा सकता है।" जीसीसी के बारे में मेरी बात प्रासंगिक है क्योंकि यह दर्शाता है कि आपका दावा है कि यह कैसे एक कार्यान्वयन कार्य गलत है। दूसरे शब्दों में, आपकी टिप्पणी का दावा है कि कार्यान्वयन का एक विशेष तरीका इसे रोकता है। लेकिन यह कार्यान्वयन नहीं है जो इसे रोकता है (हम इसे कर सकते हैं); यह भाषा की परिभाषा है।
एरिक पोस्टपिसिल

1
@ एरिक: मैं कार्यान्वयन के बारे में कुछ भी दावा करने का कोई मतलब नहीं था। मैंने निश्चित रूप से किसी विशेष का उल्लेख नहीं किया है। मेरी टिप्पणी में एक ऐसा व्यवहार बताया गया है जो आपके नियम के अनुसार है। मुझे नहीं लगता कि हम वास्तव में यहाँ किसी भी चीज़ पर असहमति जता रहे हैं - आपकी भाषा की कानून व्यवस्था सीधे दर्पण से आ सकती है। :)
को ऑर्बिट

जवाबों:


139

std::conditionalC ++ 11 से मेटा-फ़ंक्शन का उपयोग करें ।

#include <type_traits>  //include this

typedef std::conditional<sizeof(int) <= 4,
                         std::mt19937,
                         std::mt19937_64>::type Engine;

ध्यान दें कि यदि आप जिस प्रकार का उपयोग करते हैं sizeofवह एक टेम्पलेट पैरामीटर है T, तो कहें , तो आपको निम्नानुसार उपयोग करना होगा typename:

typedef typename std::conditional<sizeof(T) <= 4, // T is template parameter
                                  std::mt19937,
                                  std::mt19937_64>::type Engine;

या Engineइस पर निर्भर करें T:

template<typename T>
using Engine = typename std::conditional<sizeof(T) <= 4, 
                                         std::mt19937,
                                         std::mt19937_64>::type;

यह लचीला है , क्योंकि अब आप इसे इस रूप में उपयोग कर सकते हैं:

Engine<int>  engine1;
Engine<long> engine2;
Engine<T>    engine3; // where T could be template parameter!

4
+1 माइनर नाइटपिक: sizeof(int) <= 464-बिट विंडोज मशीन, GCC (MinGW) x64 कंपाइलर देने के बाद से चेकिंग बहुत पोर्टेबल तरीका नहीं है sizeof(int) = sizeof(long) = 4। बेहतर तरीका होगा sizeof(void*) <= 4
लीजेंड 2k

@ किंवदंतियां 2k: आपका मतलब है Engine<void*> engine4;? ;-)
नवाज़

2
@ नवाज़: बिल्कुल नहीं :) मेरा मतलब std::conditional<sizeof(void*) <= 4, std::mt19937, std::mt19937_64>पहले कोड स्निपेट में था।
लीजेंड 2k

1
@ किंवदंतियां 2k: अगर आपने मुझे प्रदान किया है तो आप इसका उपयोग क्यों करेंगे Engine<void*>? : पी
नवाज

@ नवाज़: हाहा ... यह सच है। हालांकि, मैंने सोचा कि ओपी को संभवतः एक आकार के आधार पर वास्तुकला का पता लगाने में int
नुकसान का

35

std::conditionalआप का उपयोग कर ऐसा कर सकते हैं:

using Engine = std::conditional<sizeof(int) <= 4, 
                               std::mt19937, 
                               std::mt19937_64
                               >::type;

यदि आप एक करना चाहते हैं typedef, तो आप भी ऐसा कर सकते हैं।

typedef std::conditional<sizeof(int) <= 4, 
                         std::mt19937, 
                         std::mt19937_64
                         >::type Engine

यहाँ कोई जरूरत नहीं typenameहै
gx_

@gx_ हाँ, इसे टेम्प्लेट के साथ काम करने में उपयोग किया जाता है, ठोस प्रकार नहीं।
रप्त्ज

1
@LightnessRacesinOrbit खैर, मैंने इसे थोड़ा ठीक किया।
रप्त्ज

5

यदि आपके पास C ++ 11 उपलब्ध नहीं है (हालाँकि ऐसा प्रतीत होता है कि यदि आप उपयोग करने की योजना बना रहे हैं std::mt19937), तो आप Boost Metaprogramming Library (MPL) का उपयोग करके C ++ 11 समर्थन के बिना एक ही चीज़ को लागू कर सकते हैं । यहाँ एक उदाहरण है:

#include <boost/mpl/if.hpp>
#include <iostream>
#include <typeinfo>

namespace mpl = boost::mpl;

struct foo { };
struct bar { };

int main()
{
    typedef mpl::if_c<sizeof(int) <= 4, foo, bar>::type Engine;

    Engine a;
    std::cout << typeid(a).name() << std::endl;
}

यह fooमेरे सिस्टम पर नामांकित नाम को प्रिंट करता है, क्योंकि intयहां 4 बाइट्स हैं।


1
आप if_cइसके बजाय उपयोग क्यों नहीं करते ? यह लिखना आसान होगा (और समझना) mpl::if_c<sizeof(int)<=4, foo, bar>::type:। है ना?
नवाज

1
@ नवाज़: दरअसल, यह कई मायनों में बेहतर है। मैं भूल गया था mpl::if_c। मैंने उस दृष्टिकोण का उपयोग करने के बजाय उदाहरण को अद्यतन किया।
जेसन आर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.