简体   繁体   English

专为一组类型设计许多模板

[英]Specialize Many Templates for a Set of Types

How to specialize many template for all kinds of scalar values? 如何针对各种标量值专门化许多模板? (such as int , float , size_t , uint32_t , and types defined in the stdint header)? (例如intfloatsize_tuint32_tstdint标头中定义的类型)?

Can I avoid specializing each template for each of the types? 我可以避免针对每种类型专门化每个模板吗? I don't want to use boost or other non-standard libraries if possible. 如果可能的话,我不想使用boost或其他非标准库。

There are some solutions at template specialization for a set of types : 模板专用化中,有一些针对一组类型的解决方案:

  1. Replace each template with multiple functions. 用多个功能替换每个模板。 One function for each scalar type. 每种标量类型都有一个函数。 (But there are many templates. That would mean writing many functions.) (但是有很多模板。这意味着编写许多功能。)

  2. Fail if the template takes a non-scalar type. 如果模板采用非标量类型,则失败。 (But I also want to write template for array types. This would mean I need to change the names of the functions. One set of function names for scalar-scalar calculation. Another set for scalar-matrix calculation. Yet another set for matrix-matrix calculation. If I am trying to overload operators, i guess this won't work.) (但是我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组函数名称用于标量-标量计算。另一组用于标量-矩阵计算。另一组用于矩阵-矩阵计算。如果我想重载运算符,我想这将无法正常工作。)

  3. Metaprogramming solution by Nawaz. Nawaz的元编程解决方案。 Same problem as in solution 2 for this case. 对于这种情况,与解决方案2中的问题相同。

  4. Specialize a generic template for each scalar type. 为每种标量类型专门化通用模板。 For example, write inline long getRatio<long> , inline long getRatio<float> , etc. Can work, but need to do that for the many templates. 例如,编写inline long getRatio<long>inline long getRatio<float>等。可以工作,但需要对许多模板执行此操作。

Thanks again. 再次感谢。

Example (this uses Andrew's solution. adapted for an old std library. still need c++11. compiled with intel icc -std=c++11): 示例(此示例使用Andrew的解决方案。适用于旧的std库。仍然需要c ++ 11。intel 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; 
}

Condensing this down to a smaller example, based on the discussion in the comments on the question, you have a type Matrix<T> and you wish to implement, say, operator+= . 将此问题简化为一个较小的示例,根据对该问题的评论中的讨论,您拥有Matrix<T>类型,并且希望实现,例如, operator+= The behaviour of this operator differs depending on whether the operand is a scalar or another matrix. 该运算符的行为取决于操作数是标量还是其他矩阵而有所不同。

You therefore want to provide two specialisations; 因此,您想提供两个专业: one for matrix-scalar operations, and one for matrix-matrix operations. 一种用于矩阵标量运算,另一种用于矩阵矩阵运算。 Within those, you want to accept any valid scalar type, or any valid matrix type. 其中,您要接受任何有效的标量类型或任何有效的矩阵类型。

This is a classic use case for type traits and SFINAE using std::enable_if . 这是使用std::enable_if 类型特征SFINAE的经典用例。 Define a trait is_scalar : 定义一个特征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.

And a trait is_matrix : 还有一个特性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...

Your operators will then be (member) function templates of the form: 您的操作员将成为以下形式的(成员)功能模板:

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
}

Note that is_scalar is already provided for you by the standard library! 请注意,标准库已经为您提供了is_scalar All this leaves is for you to define is_matrix specialisations for any matrix types you support. is_matrix一切就是让您为所支持的任何矩阵类型定义is_matrix专业化。

If you're trying to implement this template only for certain types you can declare them in a .cpp file, similar to this: Why can templates only be implemented in the header file? 如果您尝试仅针对某些类型实现此模板,则可以在.cpp文件中声明它们,这类似于: 为什么只能在头文件中实现模板?

If you want to allow anything to be in this template, but explicitly declare certain types, this link might be helpful: http://en.cppreference.com/w/cpp/language/template_specialization 如果要允许任何内容包含在此模板中,但显式声明某些类型,则此链接可能会有所帮助: http : //en.cppreference.com/w/cpp/language/template_specialization

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM