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

В момента пиша метафункция за оценка на изрази, нещо като 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
Специализацията на псевдоним-шаблон е еквивалентна на типа псевдоним; също име на шаблон за псевдоним никога не се извежда. [temp.псевдоним]/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