2011-12-06 11 views
46
#include <vector> 

struct A 
{ 
    void foo(){} 
}; 

template< typename T > 
void callIfToggled(bool v1, bool &v2, T & t) 
{ 
    if (v1 != v2) 
    { 
     v2 = v1; 
     t.foo(); 
    } 
} 

int main() 
{ 
    std::vector<bool> v= { false, true, false }; 

    const bool f = false; 
    A a; 

    callIfToggled(f, v[0], a); 
    callIfToggled(f, v[1], a); 
    callIfToggled(f, v[2], a); 
} 

ऊपर के उदाहरण के संकलन अगले त्रुटि पैदा करता है:क्यों वेक्टर <bool> :: संदर्भ बूल के संदर्भ में वापस नहीं आता है?

dk2.cpp: In function 'int main()': 
dk2.cpp:29:28: error: no matching function for call to 'callIfToggled(const bool&, std::vector<bool>::reference, A&)' 
dk2.cpp:29:28: note: candidate is: 
dk2.cpp:13:6: note: template<class T> void callIfToggled(bool, bool&, T&) 

मैं जी ++ का उपयोग कर (संस्करण 4.6.1) इस तरह संकलित:

g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp 

सवाल कि ऐसा क्यों होता है? vector<bool>::referencebool& नहीं है? या यह एक कंपाइलर बग है?
या, क्या मैं कुछ बेवकूफ कोशिश कर रहा हूं? :)

+12

दुर्भाग्यवश, इसके नाम के बावजूद, 'std :: vector ' 'bool' का 'वेक्टर' नहीं है। –

+1

एक कामकाज के रूप में, आप 'std :: unique_ptr (नया बूल [3]) 'का उपयोग कर सकते हैं ... –

+2

हर्ब सटर [जब कंटेनर कंटेनर नहीं है?] (Http://www.gotw.ca/publications /mill09.htm) बस इस समस्या के बारे में है। – legends2k

उत्तर

49

Vector is specialized for bool

इसे std की गलती माना जाता है। बजाय vector<char> का उपयोग करें:

template<typename t> 
struct foo { 
    using type = t; 
}; 
template<> 
struct foo<bool> { 
    using type = char; 
}; 

template<typename t, typename... p> 
using fixed_vector = std::vector<typename foo<t>::type, p...>; 

कभी कभी आप एक bool वेक्टर अंदर निहित के लिए संदर्भ पड़ सकता है। दुर्भाग्यवश, vector<char> का उपयोग करके आप केवल वर्णों के संदर्भ दे सकते हैं। यदि आपको वास्तव में bool& की आवश्यकता है, तो Boost Containers library देखें। इसमें vector<bool> का एक अनूठा संस्करण है।

+3

अच्छा कामकाज, और एलियासिंग के लिए नए 'उपयोग' वाक्यविन्यास का अच्छा डेमो। 'उपयोग' के स्मार्ट * उपयोग * के लिए –

+5

+1 (कोई इरादा नहीं है)। – Nawaz

+0

@ नवाज मैं भगवान से कसम खाता हूं कि पन का इरादा था। –

15

std::vector<bool> एक गैर अनुरूप कंटेनर है। अंतरिक्ष को अनुकूलित करने के लिए, यह bool एस पैक करता है और संदर्भ प्रदान नहीं कर सकता है।

इसके बजाय boost::dynamic_bitset का उपयोग करें।

+0

एक प्रकार का संदर्भ प्राप्त करने के लिए आपको ऑपरेटर [] का उपयोग करने की आवश्यकता है (परिणाम गतिशील_बिसेटसेट :: संदर्भ है)। यद्यपि कोई इटरेटर नहीं हैं। – reder

+2

-1 उल्लेख नहीं करने के लिए कि 'dynamic_bitset' अलग या बेहतर कैसे है। बेशक यह 'बूल' या तो वापस नहीं कर सकता है। – Potatoswatter

44

आपकी अपेक्षाएं सामान्य हैं, लेकिन समस्या यह है कि std::vector<bool> सी ++ कमेटी द्वारा एक प्रकार का प्रयोग किया गया है। यह वास्तव में एक टेम्पलेट विशेषज्ञता है जो बूल मूल्यों को स्मृति में पैक किया जाता है: प्रति बिट एक बिट।

और चूंकि आपके पास थोड़ा संदर्भ नहीं हो सकता है, तो आपकी समस्या है।

+7

+1। std :: vector केवल std :: vector द्वारा प्रदान की गई कार्यक्षमता का सबसेट का समर्थन करता है। यह बदसूरत है क्योंकि आपको एक काम करने वाले वेक्टर प्राप्त करने के लिए एक अलग प्रकार (चार) के साथ बूल को प्रतिस्थापित करना है। – josefx

+1

एक प्रयोग सबसे अधिक (यदि नहीं सभी) समिति के सदस्यों ने खेद व्यक्त किया! – curiousguy

5

बस मेरे 2 सेंट:

std::vector<bool>::reference जो

typedef unsigned long _Bit_type; 

struct _Bit_reference 
    { 
    _Bit_type * _M_p; 
    _Bit_type _M_mask; 

    // constructors, operators, etc... 

    operator bool() const 
    { return !!(*_M_p & _M_mask); } 
    }; 

इस तरह समारोह बदल रहा है के रूप में परिभाषित किया गया है struct _Bit_reference के लिए एक typedef है, यह काम करता है (अच्छी तरह से, संकलित कम से कम, परीक्षण नहीं किया) :

template< typename T > 
void callIfToggled(bool v1, std::vector<bool>::reference v2, T & t) 
{ 
    bool b = v2; 
    if (v1 != b) 
    { 
     v2 = v1; 
     t.foo(); 
    } 
} 

संपादित करें: (! v1 = v2) (! v1 = ख) मैं से हालत बदल गया है, जो कि एक अच्छा विचार है, करने के लिए नहीं था।

+1

यह काम करता है, लेकिन क्या यह एक जी ++ का विस्तार है? –

+1

यह एक विस्तार नहीं है, यह ठीक है कि जीसीसी वेक्टर विशेषज्ञता को कैसे लागू करता है। मुझे नहीं पता कि इस बारे में मानक क्या कहता है। आप इसे अपने लिए देख सकते हैं: std_bvector.h lib/gcc/mingw32/4.6.1/include/C++/बिट्स में। (आपकी निर्देशिका का पेड़ अलग हो सकता है, लेकिन संभवतः समान) – jrok

+0

निश्चित रूप से, यह एक विशिष्ट मामले के लिए काम करता है - आगे बताते हुए कि क्यों 'वेक्टर ' एक भयानक गलत नामक है - क्योंकि यह सामान्य रूप से उपयोग करने में अविश्वसनीय रूप से कठिन, कठिन, या असंभव हो जाता है कोड स्थितियां जो अन्य, _actual_ कंटेनर के लिए काम करती हैं। फिर भी, मुझे लगता है कि यहां एक उपयोगी कामकाज 'टेम्पलेट <टाइपनाम बी, टाइपनाम टी> शून्य कॉल IfToggled (B && v1, B && v2, T && t) का उपयोग करना होगा और 'v2' से रूपांतरण ऑपरेटर पर भरोसा करना होगा - जो मुझे लगता है कि दूसरा है संदर्भ अग्रेषण के लिए आभारी होने का कारण। हालांकि, नाम की गलत पसंद का बहाना नहीं है! –

13

std::vector<bool> इसकी सामग्री पैक करता है ताकि प्रत्येक बूलियन मान एक बिट में आठ बिट्स को बाइट में संग्रहीत किया जा सके। यह मेमोरी-कुशल लेकिन कम्प्यूटेशनल गहन है, क्योंकि प्रोसेसर को अनुरोधित बिट तक पहुंचने के लिए अंकगणित करना होगा। और यह bool संदर्भ या सूचक अर्थशास्त्र के साथ काम नहीं करता है, क्योंकि बाइट के भीतर बिट्स में C++ ऑब्जेक्ट मॉडल में पते नहीं हैं।

आप अभी भी std::vector<bool>::reference प्रकार का एक चर घोषित कर सकते हैं और इसे bool& पर उपयोग कर सकते हैं। यह जेनेरिक एल्गोरिदम को संगत होने की अनुमति देता है।

std::vector<bool> bitvec(22); 
std::vector<bool>::reference third = bitvec[ 2 ]; 
third = true; // assign value to referenced bit 

सी ++ 11 में, आप के आसपास इस का उपयोग करते हुए auto और && विनिर्देशक जो स्वचालित रूप से एक lvalue संदर्भ वेक्टर तत्व या एक rvalue संदर्भ एक अस्थायी करने के लिए बाध्य करने के लिए बाध्य का चयन करता है काम कर सकते हैं।

std::vector<bool> bitvec(22); 
auto &&third = bitvec[ 2 ]; // obtain a std::vector<bool>::reference 
third = true; // assign value to referenced bit 
+0

अच्छा जवाब, विशेष रूप से '&&' का उल्लेख, जो जेनेरिक कोड के लिए महत्वपूर्ण है ताकि प्रॉक्सी प्रकार/इटरेटर कभी भी उपयोगी हो सकें। बेशक, यह loops में समान रूप से अच्छी तरह से काम करता है: 'के लिए (ऑटो और इसे: bizarreContainer) ' –

1

उस में एक bool के साथ एक संरचना है, और है कि struct प्रकार का उपयोग vector<> बनाते हैं।

प्रयास करें:

vector<struct sb> जहां sb है struct {boolean b];

तो आप कह सकते हैं

push_back({true})

कर

typedef struct sbool {bool b;} boolstruct; और फिर vector<boolstruct> bs;

+०१२३५१६४१०६१
संबंधित मुद्दे