2010-02-05 11 views
11

मैं एक साधारण टेम्पलेट फ़ंक्शन को परिभाषित करना चाहता हूं जो रनटाइम मान लेता है और यह निर्धारित करता है कि यह संभावित मानों के कुछ सेट का सदस्य है या नहीं।सी ++: क्या स्थैतिक सरणी इनलाइन को परिभाषित करने का कोई तरीका है?

उपयोग:

int x; // <- pretend this came from elsewhere... 
if (isoneof(x, {5,3,9,25}) ... 

कुछ की तरह:

template <typename T, size_t size> 
bool isoneof(T value, T (&arr)[size]) 
{ 
    for (size_t i = 0; i < size; ++i) 
     if (value == arr[i]) 
      return true; 
    return false; 
} 

मुझे लगता है कि इस विफलता के लिए अभिशप्त है, जैसा कि मैंने नहीं दिख रहा है कि कैसे एक एक स्थिर सरणी इनलाइन बना सकते हैं।

मैं उपयोग कर सकते हैं:

int kPossibilities[] = {5,3,9,25}; 
if (isoneodf(6, kPossibilities)) ... 

isoneof करने के लिए एक मामूली परिवर्तन के साथ:

template <typename T1, typename T2, size_t size> 
bool isoneof(T1 value, const T2 (&arr)[size]) 
{ 
    for (size_t i = 0; i < size; ++i) 
     if (value == arr[i]) 
      return true; 
    return false; 
} 

कौन सा भी यह एक बालक और अधिक लचीला बनाता है।

क्या किसी के पास प्रस्ताव करने में कोई सुधार है? "स्थिर मूल्य इनलाइन सेट" को परिभाषित करने का एक बेहतर तरीका?

+6

यह सी के लिए समय के बारे में ++ 1x, है ना? ऐरे अक्षर पूरी तरह से मान्य हैं ... – xtofl

+0

@xtofl, यह उच्च समय है ... –

+0

इसके लिए तत्पर हैं! ;) – Mordachai

उत्तर

12

यदि आपको ऐसी चीजें पसंद हैं, तो आप Boost.Assign का बहुत खुश उपयोगकर्ता होंगे।

Boost.Assign वास्तव में साबित होता है कि इस तरह के अर्थ विज्ञान संभव है, तथापि एक असाइन आप को समझाने होगा के स्रोत पर नज़र है कि आप अपने आप को कि :) द्वारा

आप में सक्षम हो जाएगा करने के लिए नहीं करना चाहते हैं इस तथापि की तरह कुछ बनाने के लिए:

if (isoneof(x, list_of(2)(3)(5)(7)(11)) { ... 

... नकारात्मक पक्ष यह जा रहा है आप एक अंतर्निहित सरणी (धन्यवाद, मैनुअल) के बजाय पैरामीटर के रूप में boost::array उपयोग करने के लिए चाहते हैं - यह है कि एक अच्छा पल के लिए है वास्तव में उनका उपयोग करना शुरू करें:>

+0

मुझे डर है कि आप गलत हैं। Boost.Assign केवल बूस्ट :: सरणी के साथ काम करता है, अंतर्निर्मित सरणी के साथ नहीं। तो ओपी को सुझाव देते हुए "list_of" का उपयोग करने में सक्षम होने के लिए "कॉन्स बूस्ट :: सर और arr" आईआर ऑर्डर लेने के लिए अपना फ़ंक्शन बदलना होगा। – Manuel

+0

@ मैनुअल - मैंने यह नहीं कहा कि उसे कुछ भी बदलना नहीं होगा: पी –

+0

@ कॉर्नेल: काफी मेला। मैं अपनी टिप्पणी को बंद कर दूंगा लेकिन मैं इसे संपादित नहीं कर सकता। – Manuel

1

यह एक?

int ints[] = {2,3,5,7,11}; 
#define ARRAY_SIZE(Array) (sizeof(Array)/sizeof((Array)[0])) 
#define INLIST(x,array) isoneof(x,array,ARRAY_SIZE(array)) 

अलावा:

template <typename T> 
bool isoneof(const T& x, T *array, int n) 
{ 
     for(int i=0; i<n; ++i) 
       if(x==array[i]) 
         return true; 
     return false; 
} 
+3

एक सूची मैक्रो टाइपिंग नॉटिनलिस्ट, ओहनी;) –

+1

यह ओपी स्वयं सुझाए गए कदम से एक कदम * पीछे * है। ओपी का संस्करण सरणी के आकार को ठीक से (या संकलित करने में असफल) को कम करने की गारंटी देता है, जबकि सरणी पॉइंटर को क्षीण कर देती है तो यह गलत परिणाम देगा। – UncleBens

+0

परिवर्तन (ऐरे) [0] से 0 [ऐरे] [] ऑपरेटर –

5

यह अगले सी ++ मानक में संभव है।

तब तक, आप इसके आसपास काम कर सकते हैं उदा। एक स्थिर वस्तु के लिए operator, ओवरलोडिंग जो स्थिर सरणी शुरू करता है।

नोट: यह कार्यान्वयन ओ (एन^2) है और इसे अनुकूलित किया जा सकता है - यह सिर्फ विचार प्राप्त करने के लिए है।

using namespace std; 

template< typename T, size_t N > 
struct CHead { 
    T values[N]; 
    template< typename T > CHead<T,N+1> operator,(T t) { 
     CHead<T,N+1> newhead; 
     copy(values, values+N, newhead.values); 
     newhead.values[N]=t; 
     return newhead; 
    } 
    bool contains(T t) const { 
     return find(values, values+N, t) != values+N; 
    } 
}; 

struct CHeadProto { 
    template< typename T > 
    CHead<T,1> operator,(T t) { 
    CHead<T,1> h = {t}; 
    return h; 
    } 
} head; 



int main() 
{ 
    assert((head, 1,2,3,4).contains(1)); 
    return 0; 
} 
+2

+1: कोड के लिए, लेकिन अच्छा होने पर, मैं सिर्फ ',' ऑपरेटर को सिंटैक्टिक चीनी के लिए लापरवाही से अधिभारित नहीं करता:> –

+0

दिलचस्प दृष्टिकोण! प्रतिलिपि() मुझे इतना क्रिंग कर देती है कि मुझे लगता है कि मैं समाधान के लिए कहीं और देखता हूं। धन्यवाद :) – Mordachai

+0

@Mordachai: Boost पर एक नज़र डालें। अगर आपको यह कोड दिलचस्प लगता है तो साइन इन करें। वहाँ बहुत ही अच्छी चीजें हैं। – Manuel

2

पूर्णता के लिए, मैं बूस्ट.एमपीएल का उपयोग करने वाला एक समाधान पोस्ट करूंगा। निम्नलिखित कार्य करता है, लेकिन मुझे लगता है कि कॉर्नेल का समाधान सबसे अच्छा है।

#include <iostream> 
#include <boost/mpl/for_each.hpp> 
#include <boost/mpl/vector_c.hpp> 

struct Contains 
{ 
    Contains(int value, bool& result) : value(value), result(result) 
    { 
     result = false; 
    } 

    template< typename T > void operator()(T x) 
    { 
     result = result || (x == value); 
    } 

    int value; 
    bool& result; 
}; 


template <class IntList> 
bool isoneof(int val) 
{ 
    namespace mpl = boost::mpl; 
    bool result; 
    mpl::for_each<IntList>(Contains(val, result)); 
    return result; 
} 


int main() 
{ 
    namespace mpl = boost::mpl; 
    std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(4) << "\n"; 
    std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(5) << "\n"; 
} 

आप देख सकते हैं, संकलन समय सरणी इनलाइन isoneof के लिए एक टेम्पलेट तर्क के रूप में पारित कर दिया है।

+0

कूल! यह एक ठोस दृष्टिकोण की तरह लगता है। इसका परिणाम रिकर्सिव रन टाइम एल्गोरिदम में होता है, नहीं? – Mordachai

+0

बूस्ट/एमपीएल/for_each.hpp पर देखकर, मुझे लगता है कि यह 'for_each_impl :: execute()' recursively कहते हैं। चूंकि यह सभी इनलाइन है, शायद ऑप्टिमाइज़र रिकर्सिव कॉल को "अनलॉक" करने के लिए पर्याप्त स्मार्ट हैं? शायद नहीं। मुझे नहीं पता। :-) –

+0

यह भी ध्यान दें कि तुलना mpl :: vector_c के सभी तत्वों के लिए की जाएगी। यह पहले मैच पर "ब्रेक" नहीं करेगा। –

1

सी ++ 11 का उपयोग करना, यह इस तरह से लिखा जाएगा:

template <typename T> 
bool isoneof(T value, std::initializer_list<T> arr) 
{ 
    using namespace std; 

    return any_of(begin(arr), end(arr), [&](const T& x) { return x == value; }); 
} 
+0

धन्यवाद। हाँ, सी ++ 11 (और 14) इस तरह की चीज थोड़ा अच्छा बनाते हैं। – Mordachai

0

बस FYI - मैं vararg टेम्पलेट्स और प्रारंभकर्ता सूचियों का उपयोग मेरी विशेष समस्या हल:

template <typename T, typename U> 
bool isoneof(T v, U v1) { return v == v1; } 

template <typename T, typename U, typename... Args> 
bool isoneof(T v, U v1, Args ... others) { return isoneof(v, v1) || isoneof(v, others...); } 

template <typename T, typename U> 
bool isoneof(T value, std::initializer_list<U> values) 
{ 
    for (const auto & e : values) 
     if (value == e) 
      return true; 
    return false; 
} 
संबंधित मुद्दे