繁体   English   中英

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

[英]Specialize Many Templates for a Set of Types

如何针对各种标量值专门化许多模板? (例如intfloatsize_tuint32_tstdint标头中定义的类型)?

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

模板专用化中,有一些针对一组类型的解决方案:

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

  2. 如果模板采用非标量类型,则失败。 (但是我也想为数组类型编写模板。这意味着我需要更改函数的名称。一组函数名称用于标量-标量计算。另一组用于标量-矩阵计算。另一组用于矩阵-矩阵计算。如果我想重载运算符,我想这将无法正常工作。)

  3. Nawaz的元编程解决方案。 对于这种情况,与解决方案2中的问题相同。

  4. 为每种标量类型专门化通用模板。 例如,编写inline long getRatio<long>inline long getRatio<float>等。可以工作,但需要对许多模板执行此操作。

再次感谢。

示例(此示例使用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; 
}

将此问题简化为一个较小的示例,根据对该问题的评论中的讨论,您拥有Matrix<T>类型,并且希望实现,例如, operator+= 该运算符的行为取决于操作数是标量还是其他矩阵而有所不同。

因此,您想提供两个专业: 一种用于矩阵标量运算,另一种用于矩阵矩阵运算。 其中,您要接受任何有效的标量类型或任何有效的矩阵类型。

这是使用std::enable_if 类型特征SFINAE的经典用例。 定义一个特征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一切就是让您为所支持的任何矩阵类型定义is_matrix专业化。

如果您尝试仅针对某些类型实现此模板,则可以在.cpp文件中声明它们,这类似于: 为什么只能在头文件中实现模板?

如果要允许任何内容包含在此模板中,但显式声明某些类型,则此链接可能会有所帮助: http : //en.cppreference.com/w/cpp/language/template_specialization

暂无
暂无

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

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