1

次のコードは、メソッドdotProduct(It source、const size_t size)にコメントを付けた場合にのみ、gccでコンパイルされますが、このメソッドがコメントなしでコンパイルされるように、なんらかの方法で修正する必要があります。私の意図はリターンタイプの自動検出であるため、メソッドの名前は同じでなければなりません。誰かがコードをコンパイルするために修正する方法を教えてもらえますか?

#include <stdlib.h> 
#include <iterator> 
#include <iostream>  
#include <limits>

using std::cerr; 

   //! Template IF predicate implementation
  template <bool B, typename TrueResult, typename FalseResult> 
  class TemplateIf {
  public:
    //! The result of template IF predicate
    typedef TrueResult Result;
  };

  //! Template IF predicate implementation - specialization for false condition
  template <typename TrueResult, typename FalseResult>
  class TemplateIf<false, TrueResult, FalseResult> {
  public:
    //! The result of template IF predicate
    typedef FalseResult Result;
  };


  template <typename T1, typename T2>
  class DetermineComputationType {
  public:
    //! The determined result type
    // If (isSpecialized(T1) && isSpecialized(T2)) {
    typedef typename TemplateIf< std::numeric_limits<T1>::is_specialized && std::numeric_limits<T2>::is_specialized,
      // If (! isInteger(T1) && isInteger(T2) )
      //   return T1;
      typename TemplateIf< ! std::numeric_limits<T1>::is_integer && std::numeric_limits<T2>::is_integer, T1,
      // Else if (! isInteger(T2) && isInteger(T1) )
      //   return T2;
      typename TemplateIf< ! std::numeric_limits<T2>::is_integer && std::numeric_limits<T1>::is_integer, T2,
      // Else if ( sizeof(T1) > sizeof(T2) )
      //   return T1;
      typename TemplateIf< (sizeof(T1) > sizeof(T2)), T1,
      // Else if ( sizeof(T2) > sizeof(T1) )
      //   return T2;
      typename TemplateIf< (sizeof(T2) > sizeof(T1)), T2,
      // Else if ( isSigned(T2) )
      //   return T1;
      // Else
      //   return T2; 
      // }
      typename TemplateIf< std::numeric_limits<T2>::is_signed, T1, T2>::Result >::Result >::Result >::Result >::Result,
      // Else if ( sizeof(T2> > sizeof(T1) )
      //   return T2;
      // Else
      //   return T1;
      typename TemplateIf< (sizeof(T2) > sizeof(T1)), T2, T1 >::Result >::Result Result;
  };


template <typename It1,typename It2> struct DotProduct 
{   
  typedef typename std::iterator_traits<It1>::value_type VT1;   
  typedef typename std::iterator_traits<It2>::value_type VT2;   
  typedef typename DetermineComputationType<VT1,VT2>::Result Result;
};  

  template <typename R, typename Ct, typename It>
  inline R dotProductRCtIt(It source, const size_t size)
  {
    Ct result = Ct();
    for (size_t i = 0; i < size; ++i)
      result += static_cast<Ct>(source[i]) * static_cast<Ct>(source[i]);

    return static_cast<R>(result);
  }

 //! For description see cpputil::dotProduct()
  template <typename R, typename Ct, typename It, typename It2>
  inline R dotProductRCtItIt2(It source, It2 source2, const size_t size) {
    Ct result = Ct();
    for (size_t i = 0; i < size; ++i)
      result += static_cast<Ct>(source[i]) * static_cast<Ct>(source2[i]);

    return static_cast<R>(result);
  }

template <typename T>
struct DetermineSingleType {
  typedef typename std::iterator_traits<T>::value_type Result;
};

//! Convenience method - see above for description
// !!! COMMENT THIS METHOD AND IT WILL START WORKING !!!
template <typename It> 
inline typename DetermineSingleType<It>::Result  dotProduct(It source, const size_t size) {
  typedef typename DetermineSingleType<It>::Result ItType;

  return dotProductRCtIt<ItType, ItType, It>(source, size);
}

template<typename Result,typename It, typename It2> Result dotProduct(It source1, It2 source2, const size_t size) 
{
  //typedef typename std::iterator_traits<It>::value_type ItType;
  //typedef typename std::iterator_traits<It2>::value_type It2Type;
  //typedef typename DetermineComputationType<Result, ItType>::Result Ct;
 typedef typename DotProduct<It, It2>::Result Ct;

  return dotProductRCtItIt2<Result, Ct, It, It2>(source1, source2, size);
}  

template<typename It1, typename It2> typename DotProduct<It1,It2>::Result   dotProduct(It1 source1, It2 source2, const size_t size) 
{   
  typedef typename DotProduct<It1,It2>::Result Result;   
  return dotProductRCtItIt2<Result, Result, It1, It2>(source1, source2, size);
}

template<typename R, typename Ct, typename It, typename It2> R dotProduct(It source, It2 source2, const size_t size)
{
 return dotProductRCtItIt2<R, Ct, It, It2>(source, source2, size);
}

int main(int argc,char **argv) 
{   
  const char *s1 = "abc";   
  const char *s2 = "def";   
  cerr << dotProduct<int>(s1,s2,3) << "\n";   
  cerr << dotProduct(s1,s2,3) << "\n";   
  return EXIT_SUCCESS; 
}
4

2 に答える 2

1

int 型を iterator_traits に渡しています。iterator_traits テンプレートは、適切な typedef を公開するポインターとクラスでのみ機能します。

ここで、最初のオーバーロードを通過するときにコンパイラがエラーをスローする理由は明確ではありません。特に、このオーバーロードが呼び出しに対して正しくないためです。コンパイラのバグのように見えますが、100% 確実ではありません。

于 2012-08-03T08:24:28.227 に答える
-1

問題は、結果の型決定クラスが関数パラメーターに依存する必要があることです。1 つの解決策は、これに対して const size_t サイズ パラメータを「誤用」するように見えます。

template typename IdentifySingleType::value_type dotProduct(It source, St size) { ... }

呼び出しの場合: dotProduct((char *) s1, 3);

このように、結果の型決定は St の型が決定されるまで実行できません。したがって、パラメータ マッチング手順は、使用されたパラメータをテンプレート型と一致させ始めますが、char* から int への暗黙的な変換が不可能であるため、失敗します。

ただし、このソリューションの悪い点は、const size_t サイズ パラメーターをテンプレート化して誤用する必要があることです。デフォルト値を持つ別のダミー パラメータを追加しても、コンパイル エラーは防止されません。

現在、私は他のより良い解決策を知りません.sizeパラメータを誤用した解決策は良いものではありません. したがって、戻り値の型の自動決定をあきらめなければならない可能性が高いです。他のアイデアはありますか?

于 2012-08-03T12:36:42.107 に答える