簡體   English   中英

如何解析自動返回類型-C ++(模板)

[英]How to resolve automatic return type - C++ (templates)

我有一個帶有以下簽名的dotProduct方法:

template<typename It, typename It2>
typename DetermineResultType< typename std::iterator_traits<It>::value_type, typename std::iterator_traits<It2>::value_type>::Result dotProduct(It source, It2 source, const size_t size);

template<typename R, typename It, typename It2>
R dotProduct(It source, It2 source, const size_t size);

一切正常,直到我嘗試:

char * s, * s2;
int result = dotProduct<int>(s, s2, 3);

有了這個我得到的錯誤是std::iterator_traits<int>::value_type沒有定義。

如何解決此問題,以便可以自動確定第一個聲明的結果類型? (方法的名稱必須保持不變)。 我采用了一些規則來確定結果類型,但這並不重要。

基本上,問題歸結為是否定義了std::iterator_traits<It>::value_type使用非專業化的std :: iterator_traits時。 我能以某種方式檢測到嗎? 如果沒有,我還有什么其他選擇?

好的,現在該示例正常運行,但是我如何用以下方式定義我的DefineComputationType aka DefineResultType的相同技巧:???

    //! 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;
  };


   /*!
\brief Helper class for computation type determination - works for 3 types 

\tparam T1 The first type for computation type determination
\tparam T2 The second type for computation type determination 
\tparam T3 The third type for computation type determination

The result is computed in order: (T1, (T2, T3))
*/
template <typename T1, typename T2, typename T3>
class DetermineComputationType2 {
public:
//! The computation type result
typedef typename DetermineComputationType<T1, typename DetermineComputationType<T2, T3>::Result >::Result Result;
 };

template <typename T1, typename T2>
class DetermineReturnComputationType {
public:    
typedef typename std::iterator_traits<T1>::value_type T1Type;
typedef typename std::iterator_traits<T2>::value_type T2Type;    
typedef typename DetermineComputationType<T1Type, T2Type>::Result 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);
  }


/*!
\brief Returns the dot product of vectors

\param[in] source The iterator to the start of source vector
\param[in] source2 The iterator to the start of second source vector    
\param[in] size The size of vector(s)
*/
template <typename R, typename Ct, typename It, typename It2>
inline R dotProduct(It source, It2 source2, const size_t size) {
  return arithmeticsInternal::dotProductRCtItIt2<R, Ct, It, It2>(source, source2, size);  
}

//! Convenience method - see above for description
template <typename R, typename It, typename It2>
inline R dotProduct(It source, 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 arithmeticsInternal::DetermineComputationType2<R, ItType, It2Type>::Result Ct;

 return arithmeticsInternal::dotProductRCtItIt2<R, Ct, It, It2>(source, source2, size);
}

//! Convenience method - see above for description
template <typename It, typename It2>
inline typename arithmeticsInternal::DetermineReturnComputationType<It, It2>::Result dotProduct(It source, 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 arithmeticsInternal::DetermineReturnComputationType<It, It2>::Result R;

 return arithmeticsInternal::dotProductRCtItIt2<R, R, It, It2>(source, source2, size);  
 }   

這是一個如何獲取dotProduct模板函數的示例,該函數將推論返回類型或允許您明確指定返回類型:

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

using std::cerr;

template<typename It, typename It2> struct DetermineResultType;

template<>
struct DetermineResultType<char,char> {
  typedef int 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 DetermineResultType<VT1,VT2>::Result Result;
};

template<typename Result,typename It, typename It2>
Result dotProduct(It source1, It2 source2, const size_t size)
{
  Result sum = 0;
  for (size_t i=0; i!=size; ++i) {
    sum += *source1 * *source2;
  }
  return sum;
}

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 dotProduct<Result>(source1,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;
}

如果第一個參數不是迭代器,則編譯器將無法實例化DotProduct <>,因為它無法確定VT1的類型。 SFINAE將消除這種過載。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM