decayメタ関数

いつもすぐ忘れるdecay(ディケイ、と読む)メタ関数の機能、その備忘記です。
Boost.TypeTraitsからC++11のヘッダに入ったstd::decayメタ関数は、配列と関数に関して、関数テンプレートの型推論時に行われる型変換と同じことを行います。


関数テンプレートでは、配列型(T[N])はポインタ(T*)に変換されます。また、関数型(R(Args...))は関数ポインタ(R(*)(Args...))に変換されます。std::decayメタ関数に配列型を渡すとポインタ型が返され、関数型を渡すと関数ポインタ型が返されます。


以下、検証用コード:

#include <iostream>
#include <type_traits>

template <class T>
T array_decay(T x)
{
    static_assert(std::is_same<T, int*>::value, "T must be int*");
    return x;
}

template <class T>
T fp_decay(T x)
{
    static_assert(std::is_same<T, int(*)(double)>::value, "T must be int(*)(double)");
    return x;
}

int proc(double) { return 0; }

int main()
{
    // 配列型をdecayするとポインタになる
    {
        int ar[3] = {1, 2, 3};
        using result_type = std::decay<decltype(ar)>::type;
        static_assert(std::is_same<result_type, int*>::value, "");

        int* result = array_decay(ar);
    }

    // 関数型をdecayすると関数ポインタになる
    {
        // 関数の型は関数ポインタではない
        static_assert( std::is_same<decltype(proc), int(double)>::value, "");
        static_assert(!std::is_same<decltype(proc), int(*)(double)>::value, "");

        using result_type = std::decay<int(double)>::type;
        static_assert(std::is_same<result_type, int(*)(double)>::value, "");

        int(*result)(double) = fp_decay(proc);
    }
}