В этот вопрос Я привел к конкретному решению, которое включает частичные специализации шаблонных объявлений псевдонимов. Общий случай описан в этот ответ. Предположим, у меня есть шаблон класса
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>;
(Я знаю, что есть перегруженные версии для пресса, это только для иллюстрации. Смотрите мой другой пример, если хотите).
В идеале я хотел бы определить шаблон класса Number в зависимости от одного аргумента, типа, так что Number<ИНТ> равно
Number_impl<int, std::abs>;
и номер<двойной> равно
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>;
Кто-нибудь знает, если и как это можно сделать, или как это может быть достигнуто по-другому?
Обычный способ сделать это — то же самое, что стандартная библиотека делает с классом признаков, который вы можете специализировать:
#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
Вы можете добавить слой:
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;