2013-06-10 9 views
24

मैं एक क्लास टेम्पलेट कैसे बना सकता हूं जो यह लौटाता है कि इसके किसी भी विविध प्रकार पहले प्रकार के बराबर हैं या नहीं। मैं यह करने के सक्षम होना चाहते हैं:एक variadic is_same कैसे बनाएं?

is_same<T, A, B, C>::value; // true if T is one of A, B or C 

और अगर T उन प्रकारों में से किसी एक के बराबर है, इसकी स्थिर value सदस्य true, अन्यथा false हो जाएगा। मैं यह कैसे कर सकता हूँ?

+3

चूंकि आपका आशय नहीं था स्पष्ट (दो लोगों ने एक ही गलत व्याख्या की) मैंने आपके प्रश्न को थोड़ा सा जवाब देने की स्वतंत्रता ली। – syam

उत्तर

30

टेम्पलेट का उपयोग करें प्रत्यावर्तन:

template<typename T, typename... Rest> 
struct is_any : std::false_type {}; 

template<typename T, typename First> 
struct is_any<T, First> : std::is_same<T, First> {}; 

template<typename T, typename First, typename... Rest> 
struct is_any<T, First, Rest...> 
    : std::integral_constant<bool, std::is_same<T, First>::value || is_any<T, Rest...>::value> 
{}; 

static_assert(is_any<int, char, double, int>::value, "error 1"); // OK 
static_assert(is_any<int, char, double, short>::value, "error 2"); // error 
+0

धन्यवाद यह काम किया। :) –

7

ऐसा कुछ।

template<typename... Ts> 
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >; 

और संपूर्णता के लिए, मूल is_all है, जो हो सकता है: सबसे पहले, एक छोटे से metaprogramming पुस्तकालय, क्योंकि यह 2 लाइनों है जैसे कि यह सामान्य रूप से ऐसा करने के लिए कहते हैं: तो फिर is_any_same_to_first के 2 लाइन कार्यान्वयन

template<template<typename,typename>class checker, typename... Ts> 
struct is_any_to_first : std::false_type {}; 

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts> 
struct is_any_to_first<checker, T0, T1, Ts...> : 
    std::integral_constant< bool, checker<T0, T1>::value || is_any_to_first<checker, T0, Ts...>::value> 
{}; 

यह भी उपयोगी साबित:

template<template<typename,typename>class checker, typename... Ts> 
struct is_all : std::true_type {}; 

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts> 
struct is_all<checker, T0, T1, Ts...> : 
    std::integral_constant< bool, checker<T0, T1>::value && is_all<checker, T0, Ts...>::value> 
{}; 

template<typename... Ts> 
using is_all_same = is_all< std::is_same, Ts... >; 

is_all_same की Live example

ध्यान दें कि is_any_same_to_first पर कॉल करने से कुछ भी कम स्पष्ट हो रहा है। 2/3 लोग जिन्होंने मुझे इस प्रश्न का उत्तर देने का प्रयास किया, ने माना कि is_same<A,B,C> सच है अगर सभी तीन एक ही प्रकार के हैं!

+0

हम्म मैं देखता हूं कि आपने मुझसे अन्य निर्णय लिया है ('is_all_same'' is_any' के बजाय)। सच कहा जाता है, मैं इसके बारे में स्पष्टीकरण के लिए ओपी से पूछने में हिचकिचाहट करता हूं। – syam

+0

उम ... यह कोड केवल तभी काम करेगा यदि * सभी * प्रकार समान हैं। मैं देख रहा हूं कि 'टी' * * * ए ',' बी', या 'सी' है। –

2

आराम सी ++ 14 constexpr कार्यों का उपयोग करना, चीजों के इन प्रकार के बहुत कोड के लिए आसान कर रहे हैं, और शायद बहुत तेजी के साथ-साथ संकलित करने के लिए है, तो आप लिख सकते हैं:

template <class T, class ... Candidates> 
constexpr bool is_all_same() { 
    bool pairs[] = {std::is_same_v<T,Candidates>...}; 
    for(bool p: pairs) if(!p) return false; 
    return true; 
} 

template <class T, class ... Candidates> 
constexpr bool is_any_same() { 
    bool pairs[] = {std::is_same_v<T,Candidates>...}; 
    for(bool p: pairs) if(p) return true; 
    return false; 
} 

यह इस तथ्य से सक्षम है कि सी ++ 14 कॉन्स्टेक्स फ़ंक्शन में लूप के लिए हो सकता है।

10

अच्छा और साथ सी ++ 17 संक्षिप्त:

template <class T, class... Ts> 
struct is_any : std::disjunction<std::is_same<T, Ts>...> {}; 

और दोहरी:

template <class T, class... Ts> 
struct are_same : std::conjunction<std::is_same<T, Ts>...> {}; 

एक बदलाव भाव गुना का उपयोग करता है:

template <class T, class... Ts> 
struct is_any : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {}; 

template <class T, class... Ts> 
struct are_same : std::bool_constant<(std::is_same_v<T, Ts> && ...)> {}; 
संबंधित मुद्दे