15

int64_tifstd::is_integral<>::valueがtrueを返そうとしています。

それ以外の場合は、オブジェクトを呼び出しto_int64t()ます。

関数テンプレートの部分的な特殊化が許可されていないため、以下の私の試みは失敗しています。

コード

#include <type_traits>
#include <cstdint>

template<class T,bool is_integral_type>
int64_t to_int64t( const T& t )
{
        return t;
}

template<class T>
int64_t to_int64t<T,std::is_integral<T>::value>( const T& t )
{
        return t;
}

template<class T>
int64_t to_int64t<T,!std::is_integral<T>::value>( const T& t )
{
        return t.to_int64t();
}

int main()
{
        int64_t i = 64;
        auto x = to_int64t( i );
}
4

2 に答える 2

32

関数テンプレートを部分的に特殊化することはできません。一般に、関数テンプレートの特殊化を使用することはお勧めできません。

目的を達成する1つの方法は、タグディスパッチと呼ばれる手法を使用することです。これは、基本的に、追加のダミー引数の値に基づいて適切なオーバーロードを選択するフォワーダー関数を提供することで構成されます。

#include <type_traits>
#include <cstdint>

template<class T>
int64_t to_int64t( const T& t, std::true_type )
{
    return t;
}

template<class T>
int64_t to_int64t( const T& t, std::false_type )
{
    return t.to_int64t();
}

template<class T>
int64_t to_int64t( const T& t )
{
    return to_int64t(t, std::is_integral<T>());
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}

もう1つの可能性は、に基づく従来のSFINAE手法を使用することstd::enable_ifです。これは次のようになります(C ++ 11以降、関数テンプレートのデフォルトのテンプレート引数が許可されていることに注意してください)。

#include <type_traits>
#include <cstdint>

template<class T, typename std::enable_if<
    std::is_integral<T>::value>::type* = nullptr>
int64_t to_int64t( const T& t )
{
    return t;
}

template<class T, typename std::enable_if<
    !std::is_integral<T>::value>::type* = nullptr>
int64_t to_int64t( const T& t )
{
    return t.to_int64t();
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}

さらに別の可能性は、より冗長ですが、名前空間でヘルパークラステンプレート(部分的に特殊化できます)を定義しdetail、グローバルフォワーダーを提供することです-このユースケースではこの手法を使用しませんが、関連する設計状況で便利です:

#include <type_traits>
#include <cstdint>

namespace detail
{
    template<class T, bool = std::is_integral<T>::value>
    struct helper { };

    template<class T>
    struct helper<T, true>
    {
        static int64_t to_int64t( const T& t )
        {
            return t;
        }
    };

    template<class T>
    struct helper<T, false>
    {
        static int64_t to_int64t( const T& t )
        {
            return t.to_int64t();
        }
    };
}

template<class T>
int64_t to_int64t( const T& t )
{
    return detail::helper<T>::to_int64t(t);
}

int main()
{
    int64_t i = 64;
    auto x = to_int64t( i );
}
于 2013-03-24T13:23:28.890 に答える
7

あなたはただ使うことができますstd::enable_if

template<class T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
int64_t to_int64t( const T& t )
{
        return t;
}

template<class T, typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
int64_t to_int64t( const T& t )
{
        return t.to_int64t();
}
于 2013-03-24T13:23:22.267 に答える