関数テンプレートを部分的に特殊化することはできません。一般に、関数テンプレートの特殊化を使用することはお勧めできません。
目的を達成する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 );
}