6

テンプレート パラメーターを受け取る関数を作成し、関数にint渡された値が 10 未満の場合にコンパイル時エラーを発生させる方法はありますか?

次のコードは機能しませんが、私が達成したいことを示しています。

template <int number1>
void reportErrorIfLessThan10()
{
    #if(number1 < 10)
        #error the number is less than 10
    #endif
}


int maint(int argc, char**argv)
{
   reportErrorIfLessThan10<5>();//report an error!
   reportErrorIfLessThan10<12>();//ok
   return 0;
}
4

4 に答える 4

7

Boost C++ Librariesの魔法が欲しくなくて、最小限の骨が欲しいなら...

template<bool> class static_check
{
};

template<> class static_check<false>
{
private: static_check();
};

#define StaticAssert(test) static_check<(test) != 0>()

次に、StaticAssert を使用します。C++ がテンプレートに対して正しく機能しない多くの環境で実行する必要があるコードがあり、それをランタイム アサートに戻す必要があるため、これは私にとって #define です。:(

また、最良のエラー メッセージではありません。

于 2009-01-19T22:20:08.400 に答える
3

何らかの理由で Boost を使用できない場合、この例は簡単に次のように記述されます。

template <int number1>
void reportErrorIfLessThan10()
{
    typedef char number1_gt_10[number1 > 10 ? 1 : -1];
}


int maint(int argc, char**argv)
{
   reportErrorIfLessThan10<5>();//report an error!
   reportErrorIfLessThan10<12>();//ok
   return 0;
}

またはより一般的な

#define static_assert(test, message) typedef char static_assert_at_ ## __LINE__[(test) ? 1 : -1];

static_assert(true, "some message");と言うよりも読みやすいと思うので、エラーメッセージ自体を連結していませんstatic_assert(true, some_message);。ただし、これにより、ユース ケースが 1 行につき 1 つのアサートのみに制限されます。

于 2009-01-19T22:27:30.413 に答える
3
template <int number1>
typename boost::enable_if_c< (number1 >= 10) >::type 
reportErrorIfLessThan10() {
    // ...
}

enable_if単純な bool があるため、上記の _c なしでは、次のようになります。

template<bool C, typename T = void>
struct enable_if {
  typedef T type;
};

template<typename T>
struct enable_if<false, T> { };

Boostenable_ifは単純なブール値を取らないため、_c が追加された別のバージョンがあり、単純なブール値を取ります。number110未満の場合は呼び出すことができません。条件が に評価された場合、型を公開しないため、 SFINAEはそのテンプレートを可能な候補から除外します。何らかの理由で関数でテストしたい場合は、C++1x機能が利用可能であれば、次を使用できます。enable_if::typefalsestatic_assert

template <int number1>
void reportErrorIfLessThan10() {
    static_assert(number >= 10, "number must be >= 10");
}

そうでない場合は、BOOST_STATIC_ASSERT を使用できます。

template <int number1>
void reportErrorIfLessThan10() {
    BOOST_STATIC_ASSERT(number >= 10);
}

ただし、説明的なメッセージを表示する唯一の方法は static_assert を使用することです。エラー状態を説明する名前を持つ型を使用して、多かれ少なかれそれをシミュレートできます。

namespace detail {
    /* chooses type A if cond == true, chooses type B if cond == false */
    template <bool cond, typename A, typename B>
    struct Condition {
      typedef A type;
    };

    template <typename A, typename B>
    struct Condition<false, A, B> {
      typedef B type;
    };

    struct number1_greater_than_10;
}

template <int number1>
void reportErrorIfLessThan10() {
    // number1 must be greater than 10
    sizeof( typename detail::Condition< (number1 >= 10), 
             char, 
             detail::number1_greater_than_10 
            >::type ); 
}

これをここに出力します:

エラー: 不完全なタイプ 'detail::number1_greater_than_10' への 'sizeof' の適用が無効です

しかし、最初のアプローチである using で十分だと思いますenable_if。undeclared に関するエラー メッセージが表示されreportErrorIfLessThan10ます。

于 2009-01-19T22:12:44.187 に答える
0

litb と Joe は、実際に使用されている答えを既に示しています。(一般的なブール条件ではなく)問題の数値に特化することで、これを手動で行う方法を説明するだけです。

template <int N>
struct helper : helper<N - 1> { };

template <>
struct helper<10> { typedef void type; };

template <>
struct helper<0> { }; // Notice: missing typedef.

template <int N>
typename helper<N>::type error_if_less_than_10() {
}

int main() {
    error_if_less_than_10<10>();
    error_if_less_than_10<9>();
}

関数は継承できませんが、クラス (および構造体) は継承できます。したがって、このコードでは、ハードコーディングされた再帰の開始点である 10 と 0 を除くすべての N のケースを自動的かつ動的に生成する構造体も使用します。

ところで、上記のコードは実際には非常に素晴らしいエラー メッセージを表示します。

x.cpp:16: error: no matching function for call to 'error_if_less_than_10()'
于 2009-01-19T22:26:45.330 に答える