2

テンプレートの特殊化と SFINAE で遊んでいます。

次の例に関しては、物事は簡単に思えます。

    template <class T>
    void Do(T t, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
    {
        cout << "is integer" << endl;
    }

    template <class T>
    void Do(T t, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0)
    {
        cout << "is float" << endl;
    }

いいえ、std::is_array を試しましたが、std::is_array による特殊化は使用されません。

だから私はなぜ is_array が一致しないのかを試しました:

    template <int num>
    void Do( int a[num])
    {
        cout << "int array size " << num << endl;
    }

    void Do( int* x)
    {
        cout << "int*" << endl;
    }

    ...
    int e[] = { 1,2,3 };
    Do(e);
    ...

私にとって最初の謎は、"int a[num]" による特殊化がまったくキャッチされなかったことです。関数パラメーターの型は常に int* です。

参照型を使用すると、「正しい」結果が得られました。

    template <int num>
    void Do( int (&a)[num])
    {
        cout << "int array size " << num << endl;
    }

    void Do( int* &x)
    {
        cout << "int*" << endl;
    }

だから私の質問が出てきます:テンプレート関数パラメーターと組み合わせて std::is_array の合理的な使用法はありますか? そんなこと知ってる

    cout << boolalpha << std::is_array<decltype(e)>::value << endl;

正しい結果が得られます。しかし、テンプレートの選択を手動で宣言しても、機能的なアドオンはありません。関数パラメーターからのテンプレートの特殊化が配列に適合することを (SFINAE の有無にかかわらず) 検出する方法はありますか?

4

1 に答える 1

5

私はあなたがそれを自分で手に入れたと思います.secializationでそれらの型を使用したい場合は、配列を参照によってテンプレート関数に渡します.

これを行う理由は、配列からポインターへの減衰です。これは、パラメーターの型に一致する前に、テンプレート関数の引数に発生する数少ない暗黙的な変換の 1 つです。そのためT、 で配列型であることを確認しようとすると、ポインタでしたDoIt。ただし、ターゲット型が参照型の場合、配列からポインターへの減衰は発生しません。要約すると、次のようになります。

template <class T>
void Do(T& t, typename std::enable_if<std::is_array<T>::value >::type* = 0)

動作するはずです。

ところで、SFINAE を使用しない退屈な方法

template <class T, unsigned N>
void Do(T (&t)[N])

も動作します。

于 2012-11-13T13:04:27.247 に答える