为一组类型专门化许多模板 [英] Specialize Many Templates for a Set of Types

查看:24
本文介绍了为一组类型专门化许多模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何为各种标量值特化多个模板?(如intfloatsize_tuint32_t,以及stdint中定义的类型代码>标题)?

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)?

我可以避免为每种类型专门化每个模板吗?如果可能,我不想使用 boost 或其他非标准库.

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.

一组类型的模板特化:

  1. 用多种功能替换每个模板.每种标量类型一个函数.(但是模板很多.这意味着要编写很多函数.)

  1. Replace each template with multiple functions. One function for each scalar type. (But there are many templates. That would mean writing many functions.)

如果模板采用非标量类型,则失败.(但我也想为数组类型编写模板.这意味着我需要更改函数的名称.一组用于标量-标量计算的函数名称.另一组用于标量-矩阵计算.另一组用于矩阵-矩阵计算.如果我试图重载运算符,我想这行不通.)

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.)

Nawaz 的元编程解决方案.与本案例的解决方案 2 中的问题相同.

Metaprogramming solution by Nawaz. Same problem as in solution 2 for this case.

为每个标量类型专门化一个通用模板.例如,写inline long getRatioinline long getRatio等.可以工作,但需要为许多模板做.

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.

再次感谢.

示例(这使用了安德鲁的解决方案.适用于旧的标准库.仍然需要 c++11.用 intel icc -std=c++11 编译):

Example (this uses Andrew's solution. adapted for an old std library. still need c++11. compiled with 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; 
}

推荐答案

将其压缩为一个较小的示例,根据问题评论中的讨论,您有一个类型 Matrix 并且您希望实现,例如,operator+=.此运算符的行为因操作数是标量还是其他矩阵而异.

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+=. 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.

这是类型特征SFINAE 使用 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...

您的操作符将成为以下形式的(成员)函数模板:

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
}

请注意,is_scalar 已经为你通过标准库!所有这些都留给您为您支持的任何矩阵类型定义 is_matrix 特化.

这篇关于为一组类型专门化许多模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆