2010-07-01 13 views
12

अनिवार्य रूप से, स्थिति इस प्रकार है:सी ++: टेम्पलेट पैरामीटर के अनुसार सरणी भरें

मैं एक वर्ग टेम्पलेट (एक टेम्पलेट प्रकार int के पैरामीटर length का उपयोग) है और एक स्थिर सरणी लागू करने के लिए चाहते हैं। यह सरणी लंबाई length होनी चाहिए और तत्व 1 से length होनी चाहिए।

template<int length> 
class myClass{ 
    static int array[length]; 
}; 

तब मैं सरणी

// of course, the line below does not work as intended. 
template<int length> int myClass<length>::array[length]={1,2, ..., length}; 

(कैसे) इस प्राप्त किया जा सकता initalizing के लिए एक लाइन लिखना चाहते थे:

कोड अब तक इस प्रकार लग रहा है?

+0

मैं एक ऐसी ही प्रश्न पूछा कुछ समय पहले: http://stackoverflow.com/questions/2850646/fill-container-with-template-parameters। लेकिन इस सी-शैली सरणी के बजाय 'std :: tr1 :: array' के साथ ... – phlipsy

उत्तर

2

"स्थिर कन्स्ट्रक्टर" मुहावरे का प्रयोग करें।

// संपादित 2

#include <iostream> 

template<int length> 
class myClass { 
public: 
    typedef int ArrayType[length]; 

    static struct StaticData { 
     ArrayType array; 

     StaticData() 
     { 
      for (int i = 0; i < length; i++) array[i] = i; 
     } 
    } 
    static_data; 

    static ArrayType &array; 
}; 

template<int length> 
typename myClass<length>::StaticData myClass<length>::static_data; 

template<int length> 
typename myClass<length>::ArrayType &myClass<length>::array = myClass<length>::static_data.array; 

int main(int argc, char** argv) { 
    const int LEN = 5; 
    for (int i = 0; i < LEN; i++) { 
     std::cout << myClass<LEN>::array[i]; 
    } 
} 
+0

" स्थिर कन्स्ट्रक्टर मुहावरे "0 परिणाम देता है;) एक मुहावरे का अधिक नहीं हो सकता है। –

+1

http://www.google.com/search?q="static+constructor"+c%2B%2B – adf88

+1

क्षमा करें, लेकिन यह मेरे लिए जीसीसी-4.3 के तहत काम नहीं करता है, स्थिर रचनाकार कभी नहीं बुलाया जाता है ... इस तथ्य के अलावा कि हमें 'myClass :: स्टेटिक कॉन्स्ट्रक्टर MyClass :: static_constructor' की आवश्यकता है। – phlipsy

5

आपको लगता है कि सी-शैली सरणियों के साथ क्योंकि वे मूल्य अर्थ विज्ञान की जरूरत नहीं है नहीं कर सकते।

यदि आप std::tr1::array जैसे कुछ का उपयोग करते हैं, तो आप फ़ंक्शन परिणाम में प्रारंभ करके या उन मानों को उत्पन्न करने वाले इटरेटर का उपयोग करके आसानी से कर सकते हैं।

+0

+1। ऐसा करने के लिए यहां कुछ प्रकार की कक्षा की आवश्यकता है। – stinky472

+0

Boost.assign किसी भी प्रकार के कंटेनर को शुरू करने के लिए बहुत उपयोगी है: http://www.boost.org/doc/libs/1_43_0/libs/assign/doc/index.html –

1

आप एक आवरण वर्ग लिख सकते हैं, लेकिन मुझे यकीन है कि क्लीनर समाधान देखते हैं हूँ:

template <size_t length> 
class array_init_1_to_n 
{ 
    int array[length]; 

public: 

    array_init_1_to_n() 
    { 
     for (int i = 0; i < length; ++i) 
     { 
      array[i] = i + 1; 
     } 
    } 

    operator int*() 
    { 
     return array; 
    } 

    operator const int*() const 
    { 
     return array; 
    } 
}; 

template<size_t length> 
class myClass{ 
    static array_init_1_to_n<length> array; 
}; 
0

एम्बेड एक एक static constructor में पाश है कि लंबाई को चलाता है, अपने मूल रूप से प्रारंभकर्ता का उपयोग कर के रूप में उसी के लिए:

for(int i = 0; i < length; i++) 
    array[i] = i + 1; 
1

यह कठिन लगता है।

template<int length> 
class myClass 
{ 
    public: 
    myClass() 
    { 
     static InitializeArray<length> initializeArray(&array); 
    } 
    template<int length> 
    class InitializeArray 
    { 
    public: 
     InitializeArray(int* array) 
     { 
     for(int i = 0; i < length ; ++i) 
     array[i] = i; 
     } 
    }; 
    static int array[length]; 
    static myClass instance; 
}; 
template<int length> int myClass<length>::array[length]; 
template<int length> myClass myClass::instance; 
+0

यदि आप myClass को तुरंत चालू नहीं करते हैं तो क्या होता है? – fredoverflow

+0

संशोधन के बिना मैंने अभी संपादित किया है, यह काम नहीं करेगा। –

0

यहाँ Boost.MPL का उपयोग कर एक उदाहरण है:: निकटतम दृष्टिकोण है कि मैं के बारे में सोच सकते हैं निम्नलिखित होगा

#include <cstddef> 
#include <iostream> 

#include <boost/mpl/range_c.hpp> 
#include <boost/mpl/string.hpp> 

template<std::size_t length> 
struct myClass { 
    static const std::size_t Length = length; 
    typedef typename boost::mpl::c_str< boost::mpl::range_c<std::size_t, 1, length + 1> > Array; 
}; 

int main() { 
    // check whether the array really contains the indented values 
    typedef myClass<10> test; 
    for (std::size_t i = 0; i < test::Length; ++i) { 
    std::cout << test::Array::value[i] << std::endl; 
    } 
} 

ध्यान दें कि सरणी length से बड़ा है; वर्तमान में इसका आकार तय है।

0

आप एक अतिरिक्त स्थिर सदस्य जिसका निर्माता प्रविष्टियों को भरना का ख्याल रखता है की स्पष्ट टेम्पलेट इन्स्टेन्शियशन उपयोग कर सकते हैं:,

template<int length> 
class myClass{ 
public: 
    static int array[length]; 

    typedef enum{LENGTH=length} size_; 

    struct filler 
    { 
     filler(void) 
     { 
      for(int i=0;i<LENGTH;++i) 
       array[i]=i+1; 
     } 
    }; 

    static filler fill_; 
}; 

// of course, the line[s] below now do work as intended. 
template<int length> 
int myClass<length>::array[length]; 

//static member definition 
template<int length> 
typename myClass<length>::filler myClass<length>::fill_; 

//explicit template instantiation 
template myClass<5>::filler myClass<5>::fill_; 

int main(void) 
{ 
    for(int i=0;i<myClass<5>::LENGTH;++i) 
     cout<<myClass<5>::array[i]<<endl; 

    return 0; 
} 

या के बाद से एक समान (शायद बेहतर) समाधान पहले से ही बेनोइट द्वारा ऊपर दिखाया गया है, यहां एक टेम्पलेट पुनरावर्ती संस्करण है, सिर्फ मनोरंजन के लिए:

//recursive version: 
template<int length> 
class myClass{ 
public: 
    static int array[length]; 

    typedef enum{LENGTH=length} size_; 

    static void do_fill(int* the_array) 
    { 
     the_array[LENGTH-1]=LENGTH; 
     myClass<length-1>::do_fill(the_array); 
    } 

    struct filler 
    { 
     filler(void) 
     { 
      /*for(int i=0;i<LENGTH;++i) 
       array[i]=i+1;*/ 
      do_fill(array); 
     } 
    }; 

    static filler fill_; 
}; 

//explicit specialization to end the recursion 
template<> 
class myClass<1>{ 
public: 
    static int array[1]; 

    typedef enum{LENGTH=1} size_; 

    static void do_fill(int* the_array) 
    { 
     the_array[LENGTH-1]=LENGTH; 
    } 
}; 

//definition of the explicitly specialized version of the array 
//to make the linker happy: 
int myClass<1>::array[1]; 

// of course, the line below does not work as intended. 
template<int length> 
int myClass<length>::array[length]; 

//static member definition 
template<int length> 
typename myClass<length>::filler myClass<length>::fill_; 

//explicit template instantiation 
template myClass<5>::filler myClass<5>::fill_; 

int main(void) 
{ 
    for(int i=0;i<myClass<5>::LENGTH;++i) 
     cout<<myClass<5>::array[i]<<endl; 

    return 0; 
} 

अब, विभिन्न compilers टेम्पलेट प्रत्यावर्तन के विभिन्न स्तरों का समर्थन (और इस तकनीक संकलक महंगा है) हां, तो सावधान ...;-)

ओह "यहाँ ड्रेगन रहो", एक और बात, आप myClass के विशेष संस्करण में सरणी को फिर से परिभाषित करने के लिए है, तो आप सरणी instantiating से छुटकारा पा सकते की जरूरत नहीं है [1]:

//explicit specialization to end the recursion 
template<> 
class myClass<1>{ 
public: 
    typedef enum{LENGTH=1} size_; 

    static void do_fill(int* the_array) 
    { 
     the_array[LENGTH-1]=LENGTH; 
    } 
}; 
0

आप एक स्थिर समारोह में सरणी लपेट नहीं कर सकता, उदाहरण के लिए हां, तो

template<int length> 
class myClass { 
    static int* myArray() { 
     static bool initd = false; 
     static int array[length]; 
     if(!initd) { 
      for(int i=0; i<length; ++i) { 
       array[i] = i+1; 
      } 
      initd = true; 
     } 
     return array; 
    }; 
}; 

और फिर इसे तरह का उपयोग,

myClass<4>::myArray()[2] = 42; 

इसे पहले उपयोग पर शुरू किया जाएगा, और निम्नलिखित उपयोगों पर initd स्थिर है, if(!initd) गलत होगा और प्रारंभिक चरण छोड़ा जाएगा।

1

मुझे लगता है कि यह केवल सी ++ 0x में काम करता है। सी ++ 03 में जो भी आप करते हैं - आप एक गतिशील रूप से प्रारंभिक सरणी के साथ समाप्त हो जाएंगे, और इस प्रकार संभावित रूप से प्रारंभिक क्रम की समस्याएं हो सकती हैं। निम्नलिखित C++ 0x कोड में ऐसी समस्याएं नहीं होंगी।

template<int...> 
struct myArray; 

template<int N, int ...Ns> 
struct myArray<N, Ns...> : myArray<N-1, N, Ns...> { }; 

template<int ...Ns> 
struct myArray<0, Ns...> { 
    static int array[sizeof...(Ns)]; 
}; 

template<int ...Ns> 
int myArray<0, Ns...>::array[sizeof...(Ns)] = { Ns... } ; 

template<int length> 
class myClass : myArray<length> { 
    using myArray<length>::array; 
}; 
संबंधित मुद्दे