В настоящее время я пишу метафункцию для оценки выражений, что-то вроде 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
специализация.
Так что ошибки заставляют меня думать, что псевдоним шаблона не берется в параметре шаблона шаблона частичной специализации, вместо этого используется псевдоним типа.
Как вы можете видеть из примеров, это не то, что я хотел, мне нужно, чтобы псевдоним шаблона соответствовал любой другой метафункции. Есть ли способ добиться этого?
Вы этот близко! Вам нужно только использовать класс вместо псевдонима:
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
, Снова, живой пример.
Других решений пока нет …