2013-08-27 8 views
8
struct Foo { 
    void setBar(bool bar_) { bar = bar_; } 
    bool bar; 
}; 

int main() { 
    Foo f; 
    f.setBar("true"); 
} 

bool char diziden örtülü dönüşümünü önlemek için.nasıl Yukarıdaki kod <code>bool</code> beklenen burada bir karakter dizisi geçirilir halde bağlı tip dönüşüme başarıyla derler

Bu kodun derleme başarısız olmasına neden olmak mümkün mü? (İşyerindeki derleyici eski olduğundan C++ 03 çözümü tercih edildi.)

StackOverflow ile ilgili aşağıdaki soruları inceledim, ancak bu sorunu tam olarak ele almıyorlar. Preventing implicit conversion in C++, Why does the compiler choose bool over string for implicit typecast of L""?

+5

değil. Bir 'const char [5]' geçiyorsunuz. Bu, 'boole' dönüşen bir 'const char *' 'a bozulur. – juanchopanza

+0

@juanchopanza Evet, üzgünüm gönderdikten sonra fark ettim. Şimdi sorumu güncelledim. –

cevap

9

Sen const char* alır ve bir tanımını vermeyen bir işlevi bildirebilirsiniz:

void setBar(const char*); 

Bu bağlantı zaman başarısız yapacaktır. Hala diğer tüm örtük dönüştürme olsa edecektir sol konum - ... bool için yüzen, bool için ayrılmaz, herhangi işaretçi bool için

Başka bir seçenek:

struct Foo { 
    void setBar(bool bar_) {} 
private: 
    template<typename T> 
    void setBar(T bar) {} 
}; 

bir alırsınız Bu şekilde bool'dan başka bir şeyle çağırırsanız özel olma hatası. derleyici uyarısı daha az olabilir ancak

#include <type_traits> 

struct Foo 
{ 
    template <typename T> 
    void setBar(T bar_) 
    { 
    static_assert(std::is_same<bool,T>::value, "not bool"); 
    bar = bar_;   
    } 
    bool bar; 
}; 

int main() { 
    Foo f; 
    f.setBar(true); // OK 
    f.setBar("true"); // Error 
    f.setBar(1);  // Error 
} 

Alternatif olarak, aynı etkiye std::enable_if ile SFINAE kullanabilirsiniz:

+1

'private' hakkında ne? bunu kullanabilir miyiz? –

+0

@Afriza, emin olun, sadece farklı bir hata mesajı ile başarısız olur. – jrok

+1

Bağlantı süresinde başarısızlık, derleme zamanında başarısızlık kadar iyi değildir. Bu nedenle özel: void setBar (const void *); tanımsız. Buna ek olarak bir şablon kullanmamaya çalışıyorum (bool etrafında bir sarıcı sınıfınız olduğunu hayal edin). –

7

Bir seçenek setBar yapmak bir şablon ve yalnızca bool ile çalışmasını sağlamak için olurdu okunması kolay:

struct Foo 
{ 
    template<class T , 
      class = typename std::enable_if<std::is_same<bool,T>::value>::type > 
    void setBar(T bar_) 
    { 
     bar = bar_; 
    } 
    bool bar; 
}; 
+1

Bu ve C++ 03 çözümü için BOOST_STATIC_ASSERT kullanabilirsiniz. – jrok

+0

Ben de std :: enable_if' denir. – lapk

+1

@PetrBudnik İyi fikir, bir örnek ekledim. – juanchopanza

5

Her ikisinin de bu sorunu ortadan kaldırdığı ve başka avantajlar sağladığı yaygın bir deyim vardır. bool kullanmak yerine, temsil ettiği durumu daha açık bir şekilde tanımlayan özel bir tür oluşturabilirsiniz.

bool tipi yalnızca true veya false türünün genel değerini temsil ederken, gerçek kullanımda bu durumları daha spesifik bir şey ifade etmek için aşırı yüklüyorsunuz. İşte yeni bir tür tanımlamak için bir enum kullanarak bir örnek: Bu hala herhangi aritmetik veya kayan türünden örtük dönüşüm sağlar

enum Bar { ok, foobar }; 

struct Foo { 
    void setBar(Bar bar_) { bar = bar_; } 
    Bar bar; 
}; 

int main() { 
    Foo f; 
    f.setBar(foobar); // ok 
    f.setBar("true"); // error 
} 

. Bunu önlemek için, C++ 11 en enum class kullanabilir veya bu gibi kendi kesinlikle yazılan bool rulo: ** Bir `std :: string` geçen ** Sen

template<class Tag> 
struct Bool { bool value; }; 

typedef Bool<struct BarTag> Bar; 
const Bar Ok = { false }; 
const Bar FooBar = { true }; 
İlgili konular