2013-07-23 5 views
10

就職の面談では、タイプがポインタかどうかを判断するメタ機能 を書くように求められました。これは私が提示するものである :C++なしでコンパイル時アサーションを作成するには11

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

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

その後、私は私のis_pointer関数は正しいことをやっていない された場合にコンパイル時に を失敗するメタアサートを書くように頼まれました。

私はstatic_assertを使用したとき、彼は明示的に私に言った 私はC++ 98の標準を使用することができます。どうすればこれを達成できますか?あなたのケースでは

+8

私はこの時点であなたは「チェックに合格したと思います会社がC++コンパイラなどを作っていない限り、あなたが実際に言語を知っているかどうかを確認することができます。 –

答えて

5

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

は、問題を解決しているだろう:

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

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

SFINAEはそうではありません(解決策はOKですが、名前は誤用されています)。 –

+0

これは、タイプのオブジェクトを作成できる場所に限られています。他のコンテキストでそれを使用できるようにするには、偽のオブジェクトを作成する必要があります: '// namespace:assert myassert;' –

9

異なるアプローチ、無効な型のtypedefしようとしている一般的なものがあります。

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

これは、ほとんどすべてのコンテキストで使用することができ、条件がfalseの場合はコンパイラをトリップします。これは、typedef n無効な型(負の要素数の配列)。さまざまなコンテキストで使用できます。

// 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

これは純粋なC言語でも使用できます:)しかし、現在のマクロではtypedefは常にそのまま 'assert__LINE__'になります。中間の "join"マクロ呼び出しが必要な実際の行番号に '__LINE__'を展開するには:[2つのトークンを一緒に貼り付ける必要があるマクロはどうすればいいですか?](http://www.parashift.com/c++-faq /macros-with-token-pasting.html) –

3

私はBOOST_STATIC_ASSERTを使用します。コードは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__) 

(例のマニュアルを参照してください):

はここだけであなたのアイデアを与えるために、非常に単純化したバージョンです。

(ブーストの実装は、例えばsizeofと中間構造体、より良いエラーメッセージを与えるとコンパイラの広い範囲で移植可能にすると、より完全である。)

関連する問題