関数テンプレートを部分的に特化することはできませんが、クラス テンプレートを部分的に特化することはできます。
f()
これにより、次のトリックの余地が残されます。実際の作業は、元の関数がその責任を委任するプライマリ関数テンプレートと特殊化された関数テンプレートの静的メンバー関数によって行われます。
#include <iostream>
namespace detail
{
template<int A, int B>
struct helper
{
static void call() { std::cout << "f<A, B>()" << std::endl; }
};
template<int A>
struct helper<A, A>
{
static void call() { std::cout << "f<A, A>()" << std::endl; }
};
}
template<int a, int b>
void f()
{
detail::helper<a, b>::call();
}
f()
関数テンプレートの使用方法は次のとおりです。
int main()
{
f<1, 2>();
f<1, 1>();
}
これが実際の例です。
編集:
関数テンプレートがメンバー関数である場合、状況は少し複雑になりますが、関数テンプレートの部分的な特殊化をクラス テンプレートの部分的な特殊化に変換するための上記の解決策は実行可能です。
これは、コメントで提供されている例に基づいて行う方法です。
まず、クラス テンプレートを前方宣言し、helper
そのインスタンス化にクラス テンプレートA
のプライベート メンバーにアクセスする権利を付与します (追加の型パラメーターの役割はすぐにT
明らかになります)。
namespace detail
{
template<typename T, int A, int B>
struct helper;
}
template <typename a>
class A
{
public:
template<int b, int c>
void f();
private:
template<typename, int, int> friend struct detail::helper;
};
次に、helper
前に行ったようにクラス テンプレートとその特殊化を定義しますcall()
が、元のメンバー関数f()
が呼び出されたクラス オブジェクトを操作するために必要な型の関数に関数パラメーターを追加します。
namespace detail
{
template<typename T, int A, int B>
struct helper
{
static void call(T* p) { std::cout << "f<A, B>()" << std::endl; }
};
template<typename T, int A>
struct helper<T, A, A>
{
static void call(T* p) { std::cout << "f<A, A>()" << std::endl; }
};
}
f()
次に、以下に示すようにメンバー関数を定義できます。
template<typename a>
template<int b, int c>
void A<a>::f()
{
detail::helper<A<a>, b, c>::call(this);
}
そして、最終的には次のように使用します。
int main()
{
A<int> inst;
inst.f<1,1>();
inst.f<1,2>();
}
これはすべて、このlive exampleにまとめられています。