2015-10-13 5 views
1

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

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

Вместо того, чтобы оставить 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, это только для иллюстрации. См. мой другой пример, если вы хотите).

В идеале я хотел бы определить класс шаблон номера в зависимости от одного аргумента, типа, так что номер <INT> равно

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

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

+0

Вы не можете специализироваться псевдонимов шаблонов: см [здесь] (http://stackoverflow.com/questions/7801228/can-i-spe cialize-a-class-template-with-an-alias-template), используя '__Number' как имя, это не очень хорошая идея - он зарезервирован здесь [здесь] (http://stackoverflow.com/questions/228783/what -А-в-правилах о-с помощью-ан-подчеркивание-в-AC-идентификатора). По теме - почему вы просто не используете fftwpp, который предоставляет C++-оболочки для FFTW? – Rostislav

+0

@Rostislav Спасибо за предложение взглянуть на FFTW ++, я буду. Тем не менее, я все еще интересуюсь этой проблемой как конструкцией, которая может возникнуть в целом. Я изменю имя __Number на Number_impl (как в ответе Jarod42), я не знал, что такие имена были зарезервированы. – doetoe

ответ

3

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

#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

Отлично, очень элегантный. Благодаря! – doetoe

2

Вы можете добавить слой:

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

Спасибо, хорошая идея! – doetoe

Смежные вопросы