Сопоставление псевдонимов шаблона с параметрами шаблона шаблона

В настоящее время я пишу метафункцию для оценки выражений, что-то вроде boost::mpl::apply:

template<typename EXPRESSION , typename... ARGS>
using eval = typename eval_impl<EXPRESSION,ARGS...>::result;

Как видите, я использую псевдонимы шаблонов C++11, чтобы не писать typename ::result при использовании оценщика.

Среди других специализаций eval_impl (реализация метафункции оценки) имеет специализацию для случая, когда пользователь передает параметризованное выражение (такое как метафункция) и набор параметров. Другими словами, для использования eval в качестве метафункции высокого порядка для оценки метафункции с набором указанных параметров.

Для этого случая я написал специализацию следующим образом:

template<template<typename...> class F , typename... PLACEHOLDERS , typename... ARGS>
struct eval_impl<F<PLACEHOLDERS...>,ARGS...> : public F<ARGS...> {}

Теперь рассмотрим вариант использования:

template<typename ARG , typename... ARGS> using first_of = ARG;

using call = eval<first_of<_1,_2,_3,_4> , bool,float,char,int>;

Здесь мы определяем пользовательскую метафункцию first_of как псевдоним шаблона и передаем ее в eval вместе с набором параметров, которые будут вызываться (оцениваться). _1, _2... просто заполнители.

Я ожидал, что eval вызывает экземпляры со специализацией, определенной выше, но это не так. И если тип с псевдонимом — это не сам тип, а шаблон с одним параметром, GCC 4.8.1 говорит:

Ошибка: ожидался один параметр шаблона, предоставлено два

В момент создания этой eval_impl специализации.

Так что ошибки наводят меня на мысль, что псевдоним шаблона не берется в параметре шаблона шаблона частичной специализации, вместо этого сопоставляется псевдоним типа.

Как вы можете видеть в примерах, это не то, чего я не хочу, мне нужно, чтобы псевдоним шаблона соответствовал любой другой метафункции. Есть ли способ добиться этого?


person Manu343726    schedule 07.04.2014    source источник
comment
Специализация шаблона псевдонима эквивалентна типу с псевдонимом; также Псевдоним имени шаблона никогда не выводится. [временный псевдоним]/2   -  person dyp    schedule 08.04.2014
comment
Вы можете передать аргументы шаблона (как std::tuple) и метафункцию отдельно.   -  person dyp    schedule 08.04.2014


Ответы (1)


Вы это близко! Вам нужно только использовать класс вместо псевдонима:

template<typename ARG, typename... ARGS>
struct first_of { using type = ARG; };

См. живой пример.

Вы не можете использовать псевдоним напрямую, потому что

 first_of<_1,_2,_3,_4>

немедленно заменяется на _1, что не соответствует форме, ожидаемой eval_impl.

Я не считаю это ограничением, поскольку обычно мы определяем шаблонные функции в приведенной выше форме, а затем определяем дополнительные псевдонимы, такие как

template<typename ARG, typename... ARGS>
using first_of_t = typename first_of<ARG, ARGS...>::type;

для более легкого использования. Так что у нас обычно есть и то, и другое; вам придется использовать первый с eval.


Попытка 2. Также обратите внимание, что прямое использование псевдонима возможно вообще без заполнителей:

template<template<typename...> class F, typename... ARGS>
using alias_eval = F<ARGS...>;

в таком случае можно сказать

using alias_call = alias_eval<first_of_t, bool, float, char, int>;

как в первой попытке. См. обновленный пример. Но я думаю, это бесполезно, потому что вы собираетесь использовать заполнители менее тривиальным способом.


Попытка 3. Еще один вариант — отложить замену псевдонима, например.

template<template<typename...> class F, typename... PLACEHOLDERS>
struct holder {};

template<typename EXPRESSION, typename... ARGS>
struct holder_eval_impl;

template<template<typename...> class F, typename... PLACEHOLDERS, typename... ARGS>
struct holder_eval_impl<holder<F, PLACEHOLDERS...>, ARGS...> :
    public F<ARGS...> {};

template<typename EXPRESSION, typename... ARGS>
using holder_eval = typename holder_eval_impl<EXPRESSION, ARGS...>::type;

который очень близок к вашему предполагаемому синтаксису

using holder_call =
    holder_eval<holder<first_of,_1,_2,_3,_4>, bool, float, char, int>;

особенно если вы используете короткое имя для holder. Опять же, живой пример.

person iavr    schedule 07.04.2014