Частичные специализации шаблонных объявлений псевдонимов

В этот вопрос Я привел к конкретному решению, которое включает частичные специализации шаблонных объявлений псевдонимов. Общий случай описан в этот ответ. Предположим, у меня есть шаблон класса

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

Кто-нибудь знает, если и как это можно сделать, или как это может быть достигнуто по-другому?

1

Решение

Обычный способ сделать это — то же самое, что стандартная библиотека делает с классом признаков, который вы можете специализировать:

#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
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;
2

По вопросам рекламы [email protected]