2015-03-23 4 views
2

У меня есть следующая частичная специализация:аргумент шаблона с параметрами шаблона обхода

constexpr int NUM_ARGS = 3; 

template <typename, typename, int> struct Dispatcher; 

template <typename T, typename V> 
struct Dispatcher<T, V, NUM_ARGS-1> {}; 

Но теперь мне нужно сам NUM_ARGS быть аргумент шаблона в Dispatcher. Но

template <typename, typename, int, int> struct Dispatcher; 

template <typename T, typename V, int NUM_ARGS> 
struct Dispatcher<T, V, NUM_ARGS, NUM_ARGS-1> { ... 

является незаконным. Итак, каково обходное решение для этого?

И ответ на решение Pradhan, каким будет обходной путь для этой незаконной специализации?

template <int M, int N, typename... Args> struct Test; 

template <int M, typename... Args> 
struct Test<M, M-1, Args...> {}; 

где параметр шаблона по умолчанию даже не разрешен?

+0

Пожалуйста, отправьте сообщение [MCVE] (http://stackoverflow.com/help/mcve). –

+0

Вы имеете в виду, что вам нужно увидеть больше контекста? Хорошо, я вставил его в свой вопрос. – prestokeys

ответ

1

Хотя вы не можете выполнять арифметику по параметрам шаблона в аргументах специализации, вам разрешено делать это в аргументах типа. Иллюстрируя с более минимальным примером, чем тот, в вопросе:

template <int M, int N, typename Specialization = void> 
class Test 
{ 
    public: 
    void foo(){cout << "Primary template." << endl;} 
}; 

template <int M, int N> 
class Test<M, N, enable_if_t<N==M-1>> 
{ 
    public: 
    void foo(){cout << "Specialization." << endl;} 
}; 

int main() 
{ 
    Test<5,10>().foo(); 
    Test<5,4>().foo(); 
    return 0; 
} 

Выход:

Primary template. 
Specialization. 

EDIT: Для того чтобы VARIADIC аргументов, мы будем держать Specialization в качестве параметра типа без по умолчанию и используйте псевдоним шаблона, чтобы сделать интерфейс чище.

template <int M, int N, typename Specialization, typename... Rest> 
class Test 
{ 
    static_assert(std::is_same<Specialization, void>::value, "Don't use Test directly. Use TestHelper instead."); 
    public: 
    void foo(){cout << "Primary template." << endl;} 
}; 

template <int M, int N, typename... Rest> 
class Test<M, N, enable_if_t<N==M-1>, Rest...> 
{ 
    public: 
    void foo(){cout << "Specialization." << endl;} 
}; 

template <int M, int N, typename... Rest> 
using TestHelper = Test<M, N, void, Rest...>; 

int main() 
{ 
    TestHelper<5,10, int, double, char>().foo(); 
    TestHelper<5,4, int, double, char>().foo(); 
    return 0; 
} 

Coliru Demo.

+0

Хотя на первый взгляд ваш вопрос, похоже, спрашивает, как сделать арифметику с параметрами шаблона непигового типа в специализации, ваш MCVE не показывает никаких признаков того, что вы на самом деле пытаетесь это сделать - вместо этого он показывает, что вы пытаетесь использовать не константное выражение как шаблонный непиговый аргумент. Если ваш вопрос действительно о последнем, отправьте разъяснение. – Pradhan

+0

Мой вопрос не о последнем. Речь идет о том, как сделать арифметику с параметрами шаблона без типа в специализации. Поэтому изменение NUM_ARGS на constexpr не решает проблему. На самом деле NUM_ARGS больше не будет глобальным. Он должен быть перемещен внутри аргументов шаблона Диспетчера. Я не делал этого в своем вопросе, потому что это незаконно, так оно и есть. – prestokeys

+0

Хорошо, это хорошее начало. Что, если 'typename Specialization = void' не возможно начать, потому что существует пакет шаблонов, например' template class Test; 'в конце? Его нужно было бы удалить, а класс переработал бы с чем-то вроде 'template class Test;', чтобы в конце можно было поставить 'typename Specialization = void'? – prestokeys

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