2016-09-09 129 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专业化的任何您支持的矩阵类型。