2015-03-17 9 views
5

मेरे पास एक ऐसी स्थिति है जहां मुझे foo का उपयोग करके दो ओवरलोडों को अलग करने की आवश्यकता है, std::enable_if का उपयोग कर। std::enable_if को दी गई स्थिति foo के टेम्पलेट पैरामीटर के आश्रित प्रकार पर निर्भर करती है।एक शर्त के साथ std :: enable_if का उपयोग कैसे करें जो स्वयं किसी अन्य स्थिति पर निर्भर करता है?

std::enable_if का उपयोग करके इसे व्यक्त करने का सबसे अच्छा तरीका क्या है?

निम्न परीक्षण कोड जो मैंने अभी तक किया है। मुझे लगता है कि परीक्षण कोड में इच्छित व्यवहार को प्राप्त करने के लिए std::enable_if के अलावा संभवतः बेहतर तरीके हैं। हालांकि, निम्नलिखित मेरे उपयोग मामले का सरलीकृत संस्करण है जिसे स्वयं std::enable_if की आवश्यकता है।

#include <type_traits> 
#include <cassert> 

struct bar 
{ 
    using baz = int; 
}; 

template<class T> struct is_bar : std::false_type {}; 
template<> struct is_bar<bar> : std::true_type {}; 

template<class Bar> 
struct baz_type 
{ 
    using type = typename Bar::baz; 
}; 


template<class T> 
typename std::enable_if< 
    std::is_integral< 
    typename baz_type<T>::type 
    >::value, 
    int 
>::type 
    foo(T x) 
{ 
    return 7; 
} 

template<class T> 
typename std::enable_if< 
    !is_bar<T>::value, 
    int 
>::type 
    foo(T x) 
{ 
    return 13; 
} 

int main() 
{ 
    assert(foo(bar()) == 7); 
    assert(foo(0) == 13); 

    return 0; 
} 

संकलक उत्पादन:

$ g++ --version ; echo ; g++ -std=c++11 repro.cpp 
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 
Copyright (C) 2013 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 


repro.cpp: In instantiation of ‘struct baz_type<int>’: 
repro.cpp:29:3: required by substitution of ‘template<class T> typename std::enable_if<std::is_integral<typename baz_type<Bar>::type>::value, int>::type foo(T) [with T = int]’ 
repro.cpp:49:3: required from here 
repro.cpp:18:33: error: ‘int’ is not a class, struct, or union type 
    using type = typename Bar::baz; 

इस कोड संकलन नहीं है क्योंकि enable_iffoo के पहले अधिभार में इस्तेमाल नेस्टेड प्रकार T::baz पर निर्भर करता है। क्योंकि int में यह नेस्टेड प्रकार नहीं है, कोड अवैध है।

मुझे जो व्यक्त करना है उसे व्यक्त करने का सही तरीका क्या है?

+0

क्या आप क्लास टेम्पलेट के बजाय 'baz_type' उपनाम टेम्पलेट बना सकते हैं? – dyp

+2

कई विकल्प 'enable_if' का उपयोग करना है, उदा। डिफ़ॉल्ट टेम्पलेट तर्क का उपयोग कर। पहले 'is_bar' की जांच करनी चाहिए, फिर दूसरा' baz_type :: type' का उपयोग कर सकता है। मानक जनादेश है कि उनका मूल्यांकन शब्दावली क्रम में किया जाता है। – dyp

+0

@DanielFrey * shrug * मेरा अपवित्र है। हालांकि मैं इसे बहुत पठनीय नहीं मानूंगा, कम से कम [इस उत्तर] के बाद नहीं (http://stackoverflow.com/a/26533335/)। – dyp

उत्तर

2

जबकि मैंने कोलिरु पर नीचे लिखा था, @dyp ने पहले ही अपनी टिप्पणी में महत्वपूर्ण भूमिका निभाई है। निम्नलिखित क्या काम करते हैं और क्या IMHO, काफी पठनीय है, यह है:

template< 
    class T, 
    typename=typename std::enable_if<is_bar<T>::value>::type, 
    typename=typename std::enable_if<std::is_integral<typename baz_type<T>::type>::value>::type 
> 
int foo(T x) 
{ 
    return 7; 
} 

template< 
    class T, 
    typename=typename std::enable_if<!is_bar<T>::value>::type 
> 
int foo(T x) 
{ 
    return 13; 
} 

Live example

सी ++ के साथ 14, एक std::enable_if_t का उपयोग तो यह और भी कम करने के लिए होगा।

+0

आपकी मदद के लिए धन्यवाद! –

संबंधित मुद्दे

 संबंधित मुद्दे