関数テンプレートを部分的に特殊化する必要があることに気付いた場合 ( DyP の回答が示すように、この場合に必要であるという意味ではないことに注意してください)、オーバーロードに頼ることができます (この最後の更新を参照してください)。答え) または、それが不可能な場合は、その関数テンプレートをクラス テンプレートにラップし、元の関数テンプレート (およびその特殊化) を静的な非テンプレート メンバー関数に置き換えます。
namespace detail
{
template<class T, int N>
struct helper
{
static constexpr T pow(const T x){
return helper<T, N-1>::pow(x) * x;
}
};
template<class T>
struct helper<T, 1> // Unnecessary specialization! (see the edit)
{
static constexpr T pow(const T x){
return x;
}
};
template<class T>
struct helper<T, 0>
{
static constexpr T pow(const T x){
return 1;
}
};
}
次に、ヘルパー クラス テンプレートの特殊化に委譲するヘルパー関数テンプレートを提供できます。
template<int N, class T>
T constexpr pow(T const x)
{
return detail::helper<T, N>::pow(x);
}
これが実際の例です。
編集:
特殊化 forN == 1
は実際には必要ないことに注意してください。この回答の目的は主に、関数テンプレートを一般的に部分的に特殊化することの不可能性を回避する方法を示すことだったので、元のテキストに残しました。そのため、元のプログラムを少しずつ翻訳しました。
ただし、コメントでDyp が指摘したように、これで十分です。
namespace detail
{
template<class T, int N>
struct helper
{
static constexpr T pow(const T x){
return helper<T, N-1>::pow(x) * x;
}
};
template<class T>
struct helper<T, 0>
{
static constexpr T pow(const T x){
return 1;
}
};
}
アップデート:
さらに注意してください。関数テンプレートを特殊化できる場合でも(たとえば、部分的ではなく明示的な特殊化を使用して)、関数テンプレートの特殊化は通常のように動作しないため、通常はそうすることはお勧めできません。予想。
関数テンプレートの特殊化が必要と思われる状況のほとんどは、タグ ディスパッチなどのよく知られた手法を利用したオーバーロードによって実際に実現できます。Potatoswatterがコメントで例を提案し、この状況で使用できることを指摘しています。std::integral_constant
template<class T>
inline constexpr T pow(const T x, std::integral_constant<T, 0>){
return 1;
}
template<class T, int N>
inline constexpr T pow(const T x, std::integral_constant<T, N>){
return pow(x, std::integral_constant<T, N-1>()) * x;
}
template<int N, class T>
inline constexpr T pow(const T x)
{
return pow(x, std::integral_constant<T, N>());
}
ただし、「関数テンプレートの部分的な特殊化が必要と思われる問題を解決する方法」に関するこれらすべてのガイドラインは、本当に必要な場合に考慮する必要があります。この具体的なケースでは、DyP が彼の回答で示したように、そうではありません。