1

我目前正在编写一个元函数来评估表达式,例如 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专业化的实例化点。

所以错误让我认为模板别名没有被部分专业化的模板模板参数所采用,而是匹配了别名类型。

正如您在示例中看到的那样,这不是我想要的,我需要将模板别名与任何其他元函数匹配。有没有办法做到这一点?

4

1 回答 1

3

你离得这么近!您只需要使用一个类而不是别名:

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. 再次,活生生的例子

于 2014-04-07T22:23:01.837 回答