35

integer および/または double 用の特定の関数が必要な入力チェッカーを構築しています (たとえば、'isPrime' は整数に対してのみ使用可能にする必要があります)。

パラメータとして使用enable_ifしている場合、完全に機能しています:

template <class T>
class check
{
public:
   template< class U = T>
   inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0)
   {
      return BuffCheck.getInt();
   }

   template< class U = T>
   inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0)
   {
      return BuffCheck.getDouble();
   }   
};

しかし、テンプレートパラメーターとして使用している場合(http://en.cppreference.com/w/cpp/types/enable_ifで示されているように)

template <class T>
class check
{
public:
   template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type >
   inline static U readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type >
   inline static U readVal()
   {
      return BuffCheck.getDouble();
   }
};

次に、次のエラーがあります。

error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded
error: with ‘template<class T> template<class U, class> static U check::readVal()’

2番目のバージョンで何が問題なのかわかりません。

4

3 に答える 3

40

デフォルトのテンプレート引数は、テンプレートの署名の一部ではありません (したがって、両方の定義が同じテンプレートを 2 回定義しようとします)。ただし、それらのパラメーターの型は署名の一部です。だからあなたはすることができます

template <class T>
class check
{
public:
   template< class U = T, 
             typename std::enable_if<std::is_same<U, int>::value, int>::type = 0>
   inline static U readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T, 
             typename std::enable_if<std::is_same<U, double>::value, int>::type = 0>
   inline static U readVal()
   {
      return BuffCheck.getDouble();
   }
};
于 2012-06-15T18:32:28.190 に答える
10

問題は、コンパイラが同じメソッドの 2 つのオーバーロードを認識し、両方に同じ引数 (この場合はなし) と同じ戻り値が含まれていることです。そのような定義を提供することはできません。これを行う最もクリーンな方法は、関数の戻り値で SFINAE を使用することです。

template <class T>
class check
{
public:
   template< class U = T>
   static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T>
   static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal()
   {
      return BuffCheck.getDouble();
   }
};

そうすれば、2 つの異なるオーバーロードを提供できます。1 つは int を返し、もう 1 つは double を返し、特定の T を使用してインスタンス化できるのは 1 つだけです。

于 2012-06-15T18:18:55.403 に答える
3

この質問が に関するものであることは承知していますがstd::enable_if、enable_if を使用せずに同じ問題を解決する代替ソリューションを提供したいと思います。C++17 が必要です

template <class T>
class check
{
public:
   inline static T readVal()
   {
        if constexpr (std::is_same_v<T, int>)
             return BuffCheck.getInt();
        else if constexpr (std::is_same_v<T, double>)
             return BuffCheck.getDouble();
   }   
};

このコードは、実行時に記述したように見えます。すべての分岐は構文的に正しい必要がありますが、セマンティクスはそうである必要はありません。この場合、T が int の場合、getDouble はコンパイラによってチェック/使用されないため、コンパイル エラー (または警告) を引き起こしません。

関数の戻り値の型が複雑すぎて言及できない場合は、いつでもauto戻り値の型として使用できます。

于 2018-08-02T18:12:24.153 に答える