T
次の関数テンプレートを変更して、テンプレートパラメーターU
がまったく同じタイプの場合に42を返すようにするにはどうすればよいですか?
template<typename T,typename U>
int Foo()
{
return 0;
}
を使用std::is_same
すると、目的の動作を提供できます。
#include <type_traits>
template<typename T,typename U>
int Foo()
{
return std::is_same<T, U>::value ? 42 : 0;
}
慣用的な方法は、名前空間内のヘルパー関数オブジェクトに作業を委任することです。これは、が同じ場合(またはクラステンプレートで使用できる他のコンパイル時パターン)にdetail
部分的に特化できます。T
U
namespace detail {
template<typename T, typename U>
struct foo
{
int operator()() const
{
return 0;
}
};
template<typename T>
struct foo<T, T>
{
int operator()() const
{
return 42;
}
};
} // namespace detail
template<typename T, typename U>
int Foo()
{
return detail::foo<T, U>()();
}
推論可能な引数(たとえば、a will Foo(T x, U y)
)もある関数の場合、これは、関数テンプレートの引数推論の力と、クラステンプレートの特殊化機能を組み合わせたものであり、ユーザーは誰もが賢くなりません(まあ、何も呼び出さないという規則が必要です)namespace detail
直接から)
答えを完全にするために、クラスなしでコンパイル時にこの選択を行う方法は次のとおりです。
namespace detail
{
int Foo(std::true_type)
{
return 42;
}
int Foo(std::false_type)
{
return 0;
}
}
template <typename T, typename U>
int Foo()
{
return detail::Foo(std::is_same<T, U>());
}
このコンパイル時の分岐は、2つの異なるコードパスの引数に対する要件が異なる場合に重要です(ただし、この場合はありません)。たとえば、一方のパスではメンバー関数を使用し、もう一方のパスx()
ではy()
; またはあなたが指摘したように、完全に「異なる」機能ですら。
これは、私にとって、クラスの管理よりもはるかに簡単です。
これはどうですか?
#include <iostream>
template<typename T,typename U>
struct Foo {
int operator()()
{
return 0;
}
};
template<typename T>
struct Foo<T, T> {
int operator()()
{
return 42;
}
};
int main() {
std::cout << Foo<int, int>()() << std::endl;
std::cout << Foo<int, double>()() << std::endl;
}