C++ 11

2013-07-23 31 views
10

olmadan derleme zamanı iddialarını nasıl yapabilirim Bir iş görüşmesinde, bir işaretçi olup olmadığını belirleyen bir metafonksiyon yazmam istendi. Bu Sunduğum Ne geçerli: Benim is_pointer fonksiyonu doğru olanı yaptığını değilseC++ 11

Sonra bir meta-assert yazmak istendi
template <typename T> 
struct is_pointer 
{ static const bool value = false; } 

template <typename T> 
struct is_pointer<T *> 
{ static const bool value = true; } 

, derleme sırasında başarısız olacağını.

static_assert'u kullandığımda, I yalnızca C++ 98 standardını kullanabileceğimi açıkça söyledi. Bunu nasıl başarabilirim? Senin durumunda

+8

sana "çek geçti bu noktada düşünüyorum (Boost uygulaması sizeof ve bir ara yapı, daha iyi bir hata mesajı verir ve derleyici geniş bir yelpazede taşınabilir olması. Ör, daha tamamlandığında) C++ derleyicileri ya da bir şey yapmadığı sürece, görüşmenin bir parçası olan dili gerçekten biliyor muydunuz. –

cevap

5

template <bool> struct assert; 
template <> struct assert<true> {}; 

sorunu çözülmüş olurdu:

assert<!is_pointer<char>::value>();  // valid 
assert<is_pointer<char *>::value>(); // valid 

assert<is_pointer<char>::value>();  // compilation error: 
             // use of incomplete class 
+0

Bu, SFINAE'nin (çözüm tamam değil, fakat isim yanlış kullanılır) bu değil. –

+0

Bu, türden bir nesne oluşturabileceğiniz konumlarla da sınırlıdır. Başka bağlamlarda kullanabilmeniz için, sahte nesneler oluşturmanız gerekir: '// ad alanı: assert myassert; –

9

farklı yaklaşım, geçersiz bir tür typedef çalışırken ortak bir vardır:

#define static_assert(condition) \ 
     typedef char assert ## __LINE__ [((condition)?1:-1)] 

Bu çoğunlukla herhangi bir bağlamda kullanılabilir ve koşul yanlış ise derleyiciyi gezer, çünkü n geçersiz tip (negatif sayı elemanı dizisi). Bu farklı bağlamlarda kullanılabilir: Ben BOOST_STATIC_ASSERT kullanacağı

// namespace level: 
static_assert(sizeof(int)==4); 
struct type { 
    // class level: 
    static_assert(sizeof(int)==4); 
    void f() { 
     // function level 
     static_assert(sizeof(int)==4); 
    } 
}; 
+3

Bu, saf C'de bile kullanılabilir :) Ancak, mevcut makronuz ile yazılan yazım her zaman "assert__LINE__" olması gerektiği gibi; "__LINE__" öğesini gerçek satır numarasına genişletmek için bir ara "birleştir" makro çağrısına ihtiyacınız vardır: [Birlikte iki jeton yapıştırmanız gereken makrolarla ne yapılmalı?] (http://www.parashift.com/c++-faq /macros-with-token-pasting.html) –

3

. Kodu inceleyebilirsiniz: boost/static_assert.hpp.

#define JOIN(X, Y) DO_JOIN(X, Y) 
#define DO_JOIN(X, Y) X ## Y 

template<bool cond> 
struct Static_assert_helper; // incomplete type 

template<> 
struct Static_assert_helper<true> { 
    typedef int Type; 
}; 

#define STATIC_ASSERT(cond) \ 
    typedef Static_assert_helper<(cond)>::Type JOIN(Static_assert_typedef_, __LINE__) 

O (örnekler için belgelerine bakın) birçok yerde kullanılabilir:

İşte size bir fikir vermek için, bir çok basitleştirilmiş versiyonu.