2013-05-02 9 views
9

मेरे पास struct है जिसमें एक सरणी है, और मैं सरणी पर अग्रेषित करने के लिए संरचना के निर्माता को प्रारंभकर्ता सूची पास करना चाहता हूं। इसे समझने के लिए, मैं करने की कोशिश की:प्रारंभकर्ता सूची के साथ सदस्य सरणी को प्रारंभ करने का सही तरीका क्या है?

#include <initializer_list> 

struct Vector 
{ 
    float v[3]; 

    Vector(std::initializer_list<float> values) : v{values} {} 
}; 

int main() 
{ 
    Vector v = {1, 2, 3}; 
} 

Which resulted in the error:

error: cannot convert ‘std::initializer_list<float>’ to ‘float’ in initialization

v के लिए I tried using parentheses instead of braces लेकिन उस त्रुटि दिया:

error: incompatible types in assignment of ‘std::initializer_list<float>’ to ‘float [3]’

यह करने के लिए कोशिश कर रहा है के लिए मेरा मुख्य प्रेरणा से बचने के लिए है निम्नलिखित चेतावनी है कि क्लैंग उत्पन्न करता है:

template <int N> 
struct Vector 
{ 
    float v[N]; 
}; 

template <> 
struct Vector<2> 
{ 
    float x, y; 
}; 

int main() 
{ 
    Vector<2> v2 = {1.0f, 2.0f};   // Yay, works 
    Vector<3> v3 = {1.0f, 2.0f, 3.0f}; // Results in warning in clang++ 
    Vector<3> u3 = {{1.0f, 2.0f, 3.0f}}; // Must use two braces to avoid warning 
    // If I could make Vector<N> take an initializer list in its constructor, I 
    // could forward that on to the member array and avoid using the double braces 
} 

warning: suggest braces around initialization of subobject

तो मेरा प्रश्न है: मैं प्रारंभकर्ता सूची के साथ सदस्य सरणी कैसे प्रारंभ कर सकता हूं? (यानी कैसे मैं पहली बार कोड काम कर सकते हैं? या यह नहीं हो सकता है? std::copy उपयोग करने के लिए

+0

कुल के लिए, आपको एक सीटीआर की भी आवश्यकता नहीं होगी। ध्यान दें कि 'प्रारंभकर्ता_सूची' का आकार परिवर्तनीय है। 'प्रारंभकर्ता-सूची' और _list -itialization_ (जो एक भाषा निर्माण है और प्रारंभकर्ता-सूची का उपयोग कर एक ctor को कॉल करने का कारण बन सकता है) के साथ प्रारंभ करने के बीच भी एक अंतर है। – dyp

+0

आप वास्तव में ऐसा नहीं कर सकते हैं, लेकिन क्या आप इसके बजाय 'std :: array' का उपयोग कर सकते हैं? – juanchopanza

+0

वह std :: सरणी का उपयोग कर सकता है, लेकिन मैंने इसे भाषा के बारे में एक प्रश्न के रूप में पढ़ा, मानक पुस्तकालय नहीं। और, किसी के भी सम्मान के साथ, किसी को मानक लाइब्रेरी पढ़ने के लिए कहने के लिए शेक्सपियर पढ़कर अंग्रेजी सीखने के लिए एक बच्चा बता रहा है। तो std :: सरणी बहुत अच्छा जवाब नहीं है। –

उत्तर

9

यदि आपका वर्ग एक aggregate है, तो आप अपने वाक्य रचना का उपयोग कर सकते

template < std::size_t len > 
struct Vector 
{ 
    float elems[len]; 
}; 

Vector<3> v = {1.0f, 2.0f, 3.0f}; 

नोट: यह ब्रेस-एलिशन के कारण संभव है। v = {{1,2,3}}; की आवश्यकता नहीं है हालांकि यह भी संभव है। क्लैंग इस चेतावनी को जारी करता है क्योंकि स्पष्ट और कम त्रुटि-प्रवण वाक्यविन्यास डबल ब्रेसिज़ के साथ होता है (प्रारंभ करने के लिए एकऔर उप-कुल elems प्रारंभ करने के लिए एक)।

अपनी कक्षा एक समग्र नहीं है, तो आप variadic टेम्पलेट का उपयोग कर सकते हैं:

#include <array> 
#include <cstddef> 

template < std::size_t len > 
struct Vector 
{ 
    std::array < float, len > m; // also works with raw array `float m[len];` 

    template < typename... TT > 
    Vector(TT... pp) : m{{pp...}} 
    {} 

    // better, using perfect forwarding: 
    // template < typename... TT > 
    // Vector(TT&&... pp) : m{{std::forward<TT>(pp)...}} 
    // {} 
}; 

Vector<3> a = {1.0f, 2.0f, 3.0f}; 
2

प्रयास करें।

Vector(std::initializer_list<float> values) 
{ 
    std::copy(values.begin(), values.end(), v); 
} 
+0

क्या होगा यदि सूची वी की क्षमता से बड़ी है? 'Std :: array' की सिफारिश करने के लिए –

12

सादा सी शैली सरणियों आबंटित नहीं हैं। यदि आप इसके बजाय std::array का उपयोग करने के लिए स्विच करते हैं, तो प्रारंभिक मामूली हो जाता है।

#include <array> 

struct Vector 
{ 
    std::array<float, 3> v; 

    Vector(std::array<float, 3> const& values) 
    : v(values) 
    {} 
}; 

int main() 
{ 
    Vector v{{1, 2, 3}}; 
} 
+0

+1। यह प्रारंभिकरण के लिए बहुत बेहतर वाक्यविन्यास की अनुमति देता है। –

0

एक सरणी गैर स्थैतिक सदस्य प्रारंभ करने के लिए, समग्र वाक्यविन्यास का उपयोग करें। यही है, N तत्वों के साथ सीधे ब्रेस्ड-सूची भरें, जहां एन सरणी में तत्वों की संख्या है। यदि तत्व प्रकार डिफ़ॉल्ट-रचनात्मक है तो आप कम से कम N का उपयोग कर सकते हैं; गायब तत्व मूल्य-प्रारंभिक होंगे।

std::initializer_list से किसी सरणी में कोई रूपांतरण नहीं है। यहां तक ​​कि यदि आप एक स्रोत प्रकार का उपयोग कर रहे थे जो किसी सरणी संदर्भ (कभी भी कोई मान नहीं) में परिवर्तित हो सकता है, तो आप सदस्य प्रारंभकर्ता में रूपांतरण का फायदा नहीं उठा सकते हैं क्योंकि सरणी असाइन करने योग्य नहीं हैं। इन मामलों में, आपको कन्स्ट्रक्टर के शरीर के भीतर std::copy जैसे कुछ का उपयोग करना होगा।

बहुआयामी सरणी के लिए नोट, चूंकि सरणी असाइन करने योग्य नहीं हैं, इसलिए आप उप-सरणी का प्रतिनिधित्व करने के लिए केवल ब्रेस्ड-सूचियों का उपयोग करते हैं। ब्रेस एलिशन का विकल्प भी है; std::remove_all_extents<TheArrayType>::type वस्तुओं की एक फ्लैट सूची का उपयोग करके और कंपाइलर मेक-डू करेगा। (जब आंतरिक गैर-सरणी प्रकार एक अंतर्निहित चरित्र प्रकार होता है, तो आप कभी-कभी एक उद्धृत स्ट्रिंग का उपयोग बहु-आयामी सरणी के लिए अगली-से-इंटर्नस्टॉस्ट प्रारंभकर्ता के रूप में कर सकते हैं।)

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