模板化别名声明的部分特化

时间:2015-10-13 15:22:36

标签: c++ templates typedef type-alias

this question中,我被引导到一个特定的解决方案,该解决方案涉及模板化别名声明的部分特化。通用案例在this answer中描述。假设我有一个模板类

template<typename T, ...>
class X {
    // ....
};

而不是让T自由并专门化其他模板参数我处于其他参数依赖于T的情况,而单独依赖于T.作为一个非常具体的例子(比其他问题中的例子更易于管理)考虑模板类

template<typename T, T absVal(T)>
class Number_impl {
 private:
  T _t;
 public:
  Number_impl(T t): _t(t) {}
  T abs() const {return absVal(_t);}
};

可能的专业是

 Number_impl<int, std::abs>;

Number_impl<double, std::fabs>;

(我知道有超载的abs版本,这只是为了说明。如果你愿意,请参阅我的另一个例子。)

理想情况下,我想根据单个参数(类型)定义模板类Number,以便Number&lt; int&gt;等于

Number_impl<int, std::abs>;

和数字&lt; double&gt;等于

Number_impl<double, std::fabs>;

类似以下内容(不起作用):

template<typename T>
using Number = Number_impl<T, nullptr>;

template<>
using Number<int> = Number_impl<int, std::abs>;

template<>
using Number<double> = Number_impl<double, std::fabs>;

是否有人知道是否以及如何使其发挥作用,或者如何以不同的方式实现相同目标?

2 个答案:

答案 0 :(得分:4)

执行此类操作的常规方法与标准库相同 - 使用可以专门化的traits类:

#include <iostream>
#include <cmath>

template<typename T> struct NumberTraits;

template<typename T, class Traits = NumberTraits<T>>
class Number {
private:
    T _t;
public:
    Number(T t): _t(t) {}
    T abs() const {
        return Traits::abs(_t);
    }
};

template<> struct NumberTraits<int>
{
    static int abs(int i) {
        return std::abs(i);
    }
};

template<> struct NumberTraits<double>
{
    static double abs(double i) {
        return std::fabs(i);
    }
};


using namespace std;

auto main() -> int
{
    Number<int> a(-6);
    Number<double> b(-8.4);
    cout << a.abs() << ", " << b.abs() << endl;
    return 0;
}

预期产出:

6, 8.4

答案 1 :(得分:3)

您可以添加图层:

template<typename T, T absVal(T)>
class Number_impl {
private:
    T _t;
public:
    Number_impl(T t): _t(t) {}
    T abs() const {return absVal(_t);}
};

template<typename T> struct Number_helper;

template<> struct Number_helper<int>    { using type = Number_impl<int, std::abs>; };
template<> struct Number_helper<double> { using type = Number_impl<double, std::fabs>; };

template<typename T>
using Number = typename Number_helper<T>::type;