Соответствующие псевдонимы шаблона в качестве параметров шаблона

В настоящее время я пишу метафункцию для оценки выражений, что-то вроде 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 специализация.

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

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

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, Снова, живой пример.

3

Другие решения

Других решений пока нет …

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