为一组类型专门化许多模板

时间:2016-09-09 15:45:45

标签: c++ templates template-specialization

如何为各种标量值专门化许多模板? (例如intfloatsize_tuint32_t以及stdint标头中定义的类型?

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

template specialization for a set of types有一些解决方案:

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

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

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

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

  5. 再次感谢。

    实施例 (这使用了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; 
    }
    

2 个答案:

答案 0 :(得分:2)

根据对问题的评论中的讨论,将其缩小为一个较小的示例,您有@Entity public class Person { @Embedded private final Address address = new Address(); public Address getAddress() { return address; } } 类型,并且您希望实施,例如Matrix<T>。此运算符的行为取决于操作数是标量还是其他矩阵。

因此,您希望提供两个专精;一个用于矩阵标量运算,一个用于矩阵运算。在这些内容中,您希望接受任何有效的标量类型或任何有效的矩阵类型。

这是使用type traitsSFINAEstd::enable_if的经典用例。定义特征operator+=

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

请注意,标准库已经为您提供了is_scalar!所有这些离开是为您定义您支持的任何矩阵类型的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 } 特化。

答案 1 :(得分:0)

如果您尝试仅针对某些类型实施此模板,则可以在.cpp文件中声明它们,类似于:Why can templates only be implemented in the header file?

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