2016-05-20 9 views
17

की एक चर संख्या को स्वीकार कर सकता है क्या एक विविध रचनाकार में तर्कों के प्रकार को बाधित करना संभव है?मैं एक सी ++ कन्स्ट्रक्टर कैसे बना सकता हूं जो int के

क्या मैं हासिल करना चाहते हैं एक निर्माता (स्थिरांक संकलन समय पर जाना जाता है) में में पारित कर दिया डाटा स्टोर करने के लिए है:

मैं व्यक्त करने के लिए

X x1(1,3,4); 
X x2(3,4,5); 

// syntax error: identifier 'Args' 
class X { 
template<int ... Args> X(Args...) 
{ 
} 
}; 
// this works but allows other types than int 
class Y { 
template<typename ... Args> Y(Args...) 
{ 
} 
}; 

संपादित मंशा स्पष्ट करने के लिए सक्षम होना चाहते हैं एक स्थिर सरणी

तो वहाँ कुछ अन्य

template<int ...values> 
struct Z 
{ 
    static int data[sizeof...(values)]; 
}; 

template<int ... values> 
int Z<values...>::data[sizeof...(values)] = {values...}; 

और एक्स के निर्माता मैं इस तरह जेड का उपयोग करना चाहते हैं:

class X { 
    template<int ... Args> X(Args...) 
    { 
     Z<Args...>::data // do stuff with data 
    } 
}; 

है कि संभव है, मेरे पास है हमारे करते integer_sequence उपयोग करने के लिए?

उत्तर

15

के बाद से आप निम्नलिखित है:

template<int... values> 
struct Z 
{ 
    static int data[ sizeof...(values) ]; 
}; 

template <int... values> 
int Z<values...>::data[ sizeof...(values) ] = { values... }; 

आप Z<> को ints में पारित करने के लिए उपयोग कर सकते हैं std::integer_sequence<>:

struct X 
{ 
    template <int... values> 
    X(std::integer_sequence<int, values...>) 
    { 
     for (int i{ 0 }; i < sizeof...(values); ++i) 
      Z<values...>::data[ i ]; // do stuff with data 
    } 
}; 

आप इसे आसान कॉल करने के लिए बनाने के लिए अपने आप को एक सहायक प्रकार कर सकते हैं ctor:

template <int... values> 
using int_sequence = std::integer_sequence<int, values...>; 

फिर आप अपनी कक्षा की पसंद को तुरंत चालू कर सकते हैं ई तो:

int main() 
{ 
    X x(int_sequence<1, 3, 5>{}); 
} 
+1

क्या आप सुनिश्चित करते हैं कि ओपी का 'इंटी' संकलन समय स्थिरांक है? – Barry

+0

@ बैरी - हाँ, वे संकलन समय पर जाने जाते हैं! –

+0

@StaffanGustafsson - यह आपके प्रश्न में उपयोगी जानकारी होगी। –

-5

नहीं, आप इस प्रकार को बाधित नहीं कर सकते हैं। आप static_assert का उपयोग कर सकते हैं हालांकि।

static_assert(std::is_same<int, Args>::value ..., "have to be ints."); 

एक static_assert कि हालांकि तरह में एक विस्तार का उपयोग करने की कोशिश की नहीं है: कुछ इस तरह होगा। आपको एक कॉन्स्टेक्सर की आवश्यकता हो सकती है जो बूल या कुछ देता है।

+0

हां, आप इस प्रकार को बाधित कर सकते हैं। और नहीं, आपके पास 'static_assert' में पैक विस्तार नहीं हो सकता है। – Barry

14

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

#include <iostream> 
#include <initializer_list> 

void myFunc(std::initializer_list<int> args) 
{ 
    for (int i: args) std::cout << i << '\n'; 
} 
int main(){ 

    myFunc({2,3,2}); 
    // myFunc({2,"aaa",2}); error! 

} 
1

आप अपने प्रश्न संकेत मिलता है कि आप सभी की जरूरत एक संकलन समय std::integer_sequence है, जो महान है नवीनीकृत किया है।

लेकिन भविष्य के पाठकों के लिए जो यहां उत्तर की तलाश कर सकते हैं, मैं भी आपके मूल प्रश्न का उत्तर देना चाहूंगा "क्या एक विविध रचनाकार में तर्कों को प्रकार में बाध्य करना संभव है?"

हां। एक तरह से (? सबसे अच्छा तरीका है मुझे यकीन है कि नहीं कर रहा हूँ) एक अतिरिक्त टेम्पलेट पैरामीटर पर SFINAE है, इस तरह:

struct X { 
    template< 
     class... TT, 
     class E = std::enable_if_t<(std::is_same_v<TT, int> && ...)> 
    > 
    X(TT... tt) { 
     // do stuff with the ints "tt..." 
    } 
}; 

&& ... एक फोल्डिंग अभिव्यक्ति, सी ++ 17 में नया है। यदि आपका कंपाइलर फ़ोल्ड-एक्सप्रेशन का समर्थन नहीं करता है, तो बस उसे हाथ से लुढ़का all_of से प्रतिस्थापित करें।

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

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