匹配模板别名作为模板模板参数 [英] Matching template aliases as template template parameters

查看:298
本文介绍了匹配模板别名作为模板模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在写一个元函数来评估表达式,例如boost :: mpl :: apply:

  typename EXPRESSION,typename ... ARGS> 
使用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

现在考虑一个用例:

  template< typename ARG,typename ... ARGS>使用first_of = ARG; 

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

这里我们定义一个自定义元函数 first_of 一个模板别名,我们将它与一组要调用(评估)的参数一起传递给 eval _1 _2 ...只是占位符。



我希望 eval 调用实例上面定义的专门化,但它不是。
如果别名类型不是类型本身,而是一个单参数模板,GCC 4.8.1说:


错误:预期一个模板参数,提供两个


eval_impl specialization。



因此,错误让我认为模板别名不是在部分专门化的模板模板参数中采用的,别名类型



正如你在例子中看到的,这不是我不知道,我需要模板别名匹配作为任何其他元功能。 有什么方法可以实现这一点?

解决方案

关!您只需要使用类而不是别名:

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

请参阅 live example



您不能直接使用别名,因为

  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< typename ...>类F,类型名... ARGS> 
using alias_eval = F< ARGS ...> ;;

在这种情况下,您可以说

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

。请参见更新示例。但我想这是没有用的,因为你打算以一个不太平凡的方式使用占位符。






尝试 替换别名,例如。 ; template< typename ...>类F,类型名... 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;

这非常接近你想要的语法

 使用holder_call = 
holder_eval< holder< first_of,_1,_2,_3,_4>,bool,float,char,int&

特别是如果您使用 holder 。同样,实例


I'm currently writting a metafunction to evaluate expressions, something like boost::mpl::apply:

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

As you can see, I'm using C++11 template aliases to avoid writting typename ::result when using the evaluator.

Among other specializations, eval_impl (The implementation of the evaluation metafunction) has an specializationfor the case the user passes a parametrized expression (Such as a metafunction) and a set of parameters. In other words, for using eval as a high-order metafunction to evaluate a metafunction with a set of specified parameters.

For that case, I have written a specialization as follows:

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

Now consider a use case:

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

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

Here we define a custom metafunction first_of as a template alias, and we pass it to eval together with a set of parameters to be called (evaluated) with. _1, _2... are just placeholders.

I have expected that eval call instances the specialization defined above, but it doesn't. And if the aliased type is not a type itself, but a one-parameter template, GCC 4.8.1 says:

Error: Expected one template parameter, two provided

At the point of instantation of that eval_impl specialization.

So that errors give me to think that the template alias is not taken in the template template parameter of the partial specialization, the aliased type is matched instead.

As you can see in the examples, thats not what I wan't, I need the template alias to be matched as any other metafunction. Is there any way to achieve that?

解决方案

You are this close! You only need to use a class instead of an alias:

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

See live example.

You cannot use an alias directly because

 first_of<_1,_2,_3,_4>

is immediately substituted for _1, which is not of the form expected by eval_impl.

I don't find this is a limitation because we usually define template functions in the above form, and then define additional aliases like

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

for easier use. So we usually have both; you'll have to use the former with eval.


Attempt 2. Also note that direct use of an alias is possible without placeholders at all:

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

in which case you can say

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

as in your first attempt. See updated example. But I guess this is of no use because you intend to use placeholders in a less trivial way.


Attempt 3. Yet another option is to delay substitution of the alias, e.g.

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;

which is very close to your intended syntax

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

especially if you use a short name for holder. Again, live example.

这篇关于匹配模板别名作为模板模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆