2016-05-23 18 views
15

मैं निम्नलिखित पैटर्न सामान्यीकरण करने के लिए चाहते हैं के ऊपर मेटा-यात्रा:variadic टेम्पलेट्स तर्क

template<class A1, class A2, class A3> 
class Foo { 
protected: 
    template<class T> 
    void foo(const T& t) {...do stuff...} 
public: 
    void bar(const A1& a) { foo(a); } 
    void bar(const A2& a) { foo(a); } 
    void bar(const A3& a) { foo(a); } 
}; 

ऊपर दृष्टिकोण बढ़ रही बहस की संख्या के साथ पैमाने पर नहीं है। तो, मैं करना चाहता हूं:

template<class As...> 
class Foo { 
protected: 
    template<class T> 
    void foo(const t& a) {...do stuff...} 
public: 
    for each type A in As declare: 
    void bar(const A& a) { foo(a); } 
}; 

क्या ऐसा करने का कोई तरीका है?

+1

bar में एक चेक के लिए हो सकता है कर सकते हैं, इसमें * समान * प्रकार कई बार होते हैं या अनुक्रम अद्वितीय प्रकार होंगे? – Nim

उत्तर

9

मामले में आप वास्तव में bar रों की जरूरत नहीं है और इसके बजाय सिर्फ foo बाध्य करने की आवश्यकता - हम केवल एक प्रकार के लिए परिवर्तनीय के साथ यह करने के लिए एक कॉल अनुमति देने के लिए उपयोग कर सकते हैं SFINAE A रों में से एक:

template <class... As> 
class Foo { 
public: 
    template <class T, 
     class = std::enable_if_t<any<std::is_convertible<T, As>::value...>::value>> 
    void foo(T const&) { ... } 
}; 

हम कहाँकी तरह कुछ के साथ any लागू कर सकते हैंचाल:

template <bool... b> struct bool_pack { }; 
template <bool... b> 
using any = std::integral_constant<bool, 
    !std::is_same<bool_pack<b..., false>, bool_pack<false, b...>>::value>; 
+0

के लिए पैक विस्तार की अनुमति होगी enable_if_t सी ++ 14 है? – user3612643

+0

@ user3612643 हां, लेकिन सी ++ 11 में लागू करने योग्य। – Barry

0
template<class A, class Foo_t> 
class bar_t { 
public: 
    void bar(const A &a) { Foo_t::foo(a); } 
}; 


template<class ...As> 
class Foo : bar_t<As, Foo<As...> >... { 
protected: 
    template<class T> 
     void foo(const T& a) { /* do stuff */ } 
}; 
+0

यह बार() एस के अलावा एकाधिक foo() s घोषित करने जा रहा है, जो कि नहीं पूछा गया था। इसके अलावा, विरासत के कारण, Foo <...> :: बार() डिफ़ॉल्ट रूप से, बार() के शीर्षतम उदाहरण तक हल करने जा रहा है। –

+0

@SamVarshavchik आपकी टिप्पणी के लिए धन्यवाद। हालांकि, मुझे यकीन नहीं है कि आप क्या कह रहे हैं। जहां तक ​​मैं समझता हूं, वहां एक फ़ंक्शन टेम्पलेट 'फूर' है, इसकी कई तात्कालिकताएं हैं। –

+1

@ एम। एलागगन शायद यह आपकी मदद करेगा यदि आप अपने उत्तर में अपने कोड का स्पष्टीकरण देते हैं। – TartanLlama

6
template <class CRTP, class A, class... As> 
struct FooBar 
{ 
    void bar(const A& a) 
    { 
     static_cast<CRTP*>(this)->foo(a); 
    } 
}; 

template <class CRTP, class A, class B, class... As> 
struct FooBar<CRTP, A, B, As...> : FooBar<CRTP, B, As...> 
{ 
    using FooBar<CRTP, B, As...>::bar; 

    void bar(const A& a) 
    { 
     static_cast<CRTP*>(this)->foo(a); 
    } 
}; 

template <class... As> 
class Foo : FooBar<Foo<As...>, As...> 
{ 
    template <class, class, class...> 
    friend struct FooBar; 

protected: 
    template <class T> 
    void foo(const T& a) { } 

public: 
    using FooBar<Foo, As...>::bar; 
}; 

DEMO

+0

नाइस के लिए नहीं है, क्या "बार" में से किसी एक से छुटकारा पाने का कोई तरीका है? – user3612643

+0

@ user3612643 http://coliru.stacked-crooked.com/a/7fdab11ffe783975 –

+0

मतलब "नहीं" ... मुझे लगता है कि आपको टर्मिनल विस्तार बिंदु की आवश्यकता है जो मध्यवर्ती से अलग है? – user3612643

5
template <class A, class... As> 
class Foo : public Foo<As...> 
{ 
protected: 
    using Foo<As...>::foo; 
public: 
    using Foo<As...>::bar; 
    void bar(const A& a) { foo(a); } 
}; 

template <class A> 
class Foo<A> 
{ 
protected: 
    template <class T> 
    void foo(const T& t) { } 
public: 
    void bar(const A& a) { foo(a); } 
}; 

Piotr Skotnicki's answer लिए एक समान व्यर्थ में, इस टेम्पलेट तर्क के सभी के लिए bar भार के साथ एक वर्ग का निर्माण करने के उत्तराधिकार का उपयोग करता है। हालांकि यह थोड़ा सा क्लीनर है, केवल एक वर्ग टेम्पलेट के साथ ही आंशिक विशेषज्ञता है।

11

एक और दृष्टिकोण variadic अनुक्रम यदि प्रकार, और एक उपयोगी त्रुटि संदेश के साथ barf अनुक्रम में है परीक्षण करने के लिए, यह किसी भी विरासत चाल से बचने के ..

#include <iostream> 

struct E {}; 
struct F {}; 

template <class... As> 
class Foo 
{ 
    template <typename U> 
    static constexpr bool contains() { 
     return false; 
    } 

    template <typename U, typename B, typename ...S> 
    static constexpr bool contains() { 
     return (std::is_same<U, B>::value)? true : contains<U, S...>(); 
    } 

protected: 
    template <class T> 
    void foo(const T& a) { std::cout << __PRETTY_FUNCTION__ << std::endl; } 

public: 
    template <class T> 
    void bar(const T& a) { 
     static_assert(contains<T, As...>(), "Type does not exist"); 
     foo(a); 
    } 
}; 

int main() 
{ 
    Foo<E, F, E, F> f; 
    f.bar(F{}); 
    f.bar(E{}); 
    f.bar(1); // will hit static_assert 
} 
संबंधित मुद्दे