7

T次の関数テンプレートを変更して、テンプレートパラメーターUがまったく同じタイプの場合に42を返すようにするにはどうすればよいですか?

template<typename T,typename U>
int Foo()
{
  return 0;
}
4

4 に答える 4

14

を使用std::is_sameすると、目的の動作を提供できます。

#include <type_traits>

template<typename T,typename U>
int Foo()
{
    return std::is_same<T, U>::value ? 42 : 0;
}
于 2013-01-31T21:27:52.600 に答える
5

慣用的な方法は、名前空間内のヘルパー関数オブジェクトに作業を委任することです。これは、が同じ場合(またはクラステンプレートで使用できる他のコンパイル時パターン)にdetail部分的に特化できます。TU

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直接から)

于 2013-01-31T21:36:49.820 に答える
3

答えを完全にするために、クラスなしでコンパイル時にこの選択を行う方法は次のとおりです。

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(); またはあなたが指摘したように、完全に「異なる」機能ですら。

これは、私にとって、クラスの管理よりもはるかに簡単です。

于 2013-02-01T07:27:10.510 に答える
1

これはどうですか?

#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;
}
于 2013-01-31T21:38:28.123 に答える