2016-09-09 128 views
1

如何針對各種標量值專門化很多模板? (如int,float,size_t,uint32_t和在stdint標題中定義的類型)?針對一組類型專門設計很多​​模板

我可以避免爲每種類型專門化每個模板嗎? 如果可能,我不想使用boost或其他非標準庫。

那裏template specialization for a set of types有一些解決方案:

  1. 替換每個模板具有多種功能。每種標量類型都有一個函數。 (但是有很多模板,這意味着需要編寫很多功能。)

  2. 如果模板採用非標量類型,則會失敗。 (但是我也想爲數組類型編寫模板,這意味着我需要改變函數的名字,一個用於標量標量計算的函數名稱,另一個用於標量矩陣計算,另一個用於矩陣 - 矩陣計算如果我試圖超載運營商,我猜這不會工作。)

  3. Nawaz元編程解決方案。對於這種情況,解決方案2中的問題相同。

  4. 爲每個標量類型專門設計一個通用模板。例如,編寫inline long getRatio<long>,inline long getRatio<float>等。可以工作,但需要爲許多模板執行此操作。

再次感謝。

例 (這使用安德魯的解決方案適用於一個古老的性病庫還需要C++ 11採用英特爾編譯ICC -std = C++ 11。):

#define STD_POORMAN stdpoor 
namespace stdpoor{ 
    template<bool B, class T = void> 
    struct enable_if_t {}; 
    template<class T> 
    struct enable_if_t<true, T> { typedef T type; }; 

    template<class T, T v> 
    struct integral_constant { 
     static constexpr T value = v; 
     typedef T value_type; 
     typedef integral_constant type; 
     constexpr operator value_type() const { 
      noexcept return value; 
     } 
     constexpr value_type operator()() const { 
      noexcept return value; 
     } 
    }; 

    typedef integral_constant<bool,true> true_type; 
    typedef integral_constant<bool,false> false_type; 
} 
template <typename T> 
class SimpleArray; 

template <typename T> 
struct is_ndscalar : STD_POORMAN::false_type {}; 
// Specialisations for supported scalar types: 
template <> struct is_ndscalar<int> : STD_POORMAN::true_type {}; 
template <> struct is_ndscalar<float> : STD_POORMAN::true_type {}; 
template <> struct is_ndscalar<double> : STD_POORMAN::true_type {}; 
template <> struct is_ndscalar<long> : STD_POORMAN::true_type {}; 
template <> struct is_ndscalar<long long> : STD_POORMAN::true_type {}; 



template <typename T> 
class SimpleArray{ 
    public: 
     T* ar_data; //pointer to data 
     int size; //#elements in the array 
     SimpleArray(T* in_ar_data, int in_size){ 
      ar_data = in_ar_data; 
      size = in_size; 
     }; 

     template <typename T> 
     void operator+=(const SimpleArray<T>& B){ 
      //array-array += 
      int i; 
      for(i = 0; i < size; ++i){ 
       ar_data[i] += B.ar_data[i]; 
      } 
     } 

     template <typename T> 
     STD_POORMAN::enable_if_t<is_ndscalar<T>::value, void> 
     operator+=(const T b){ 
      //array-scalar += 
      int i; 
      for(i = 0; i < size; ++i){ 
       ar_data[i] += b; 
      } 
     } 
}; 

int main(void){ 
    int base_array[10]; 
    SimpleArray<int> A(base_array, 10); 
    A += A; 
    A += 3; 
} 
+1

你正試圖解決什麼問題?這是非常廣泛的。 – Barry

+0

我是第二個巴里關於狹義問題陳述的請求。目前尚不清楚您是否僅僅允許將一些模板用於您確定爲「標量類型」的任何事物,對於這些模板,SFINAE和適當的特徵足夠了,或者您是否需要這些特化來包含「int '比較'float'(例如)。一個具體的例子可能會導致更有針對性的建議。 – Andrew

+0

爲數組操作編寫一個小型庫,類似於Python的numpy庫。此時,我希望專門化每個模板以進行標量類型的計算(例如運算符* =,+ =等),並且還可以針對所有矩陣類型(int的矩陣,float的矩陣等)專門化模板。 – rxu

回答

1

根據對問題的評論中的討論,將其縮小爲一個較小的示例,您有一個類型Matrix<T>,並且您希望執行operator+=。該運算符的行爲根據操作數是標量還是其他矩陣而不同。

因此你想提供兩個專業;一個用於矩陣標量運算,另一個用於矩陣運算。在那些內部,你想要接受任何有效的標量類型或任何有效的矩陣類型。

這是type traitsSFINAE使用std::enable_if的經典用例。定義一個特質is_scalar

// Base template: 
template <typename T> 
struct is_scalar : std::false_type {}; 

// Specialisations for supported scalar types: 
template <> struct is_scalar<int> : std::true_type {}; 
template <> struct is_scalar<float> : std::true_type {}; 
template <> struct is_scalar<double> : std::true_type {}; 
// etc. 

而且性狀is_matrix

// Base template: 
template <typename T> 
struct is_matrix : std::false_type {}; 

// Specialisations: 
template<typename T> 
struct is_matrix<Matrix<T>> : std::true_type {}; 
// and possibly others... 

那麼你的運營商將是這樣的形式(成員)函數模板:

template <typename T> 
std::enable_if_t<is_scalar<T>::value, Matrix&> operator+=(const T& rhs) { 
    // Implementation for addition of scalar to matrix 
} 

template <typename T> 
std::enable_if_t<is_matrix<T>::value, Matrix&> operator+=(const T& rhs) { 
    // Implementation for addition of matrix to matrix 
} 

注意is_scalar已經由標準庫爲您提供!所有這些葉子都是爲您定義is_matrix專業化的任何您支持的矩陣類型。