【发布时间】:2014-10-21 10:20:44
【问题描述】:
在 tuple continuation monad 之后,假设我定义了一个函子 std_tuple 以从 monad-tuple 的范畴转到 std::tuple:
auto std_tuple = [](auto... args)
{
return [=](auto f){ return f(std::make_tuple(args...)); };
};
现在我们可以在期望 std::tuple 的上下文中使用 monad-tuples:
template<typename... ARGS>
void f( const std::tuple<ARGS...>& t ){}
int main()
{
tuple(1,2,3)(std_tuple)(f);
}
到目前为止一切顺利。除了这不编译。 Clang 3.4.1 抱怨:
注意:候选模板被忽略:无法推断模板参数“$auto-1-0”
在std_tuple 函子内的f(t) 调用上。
这是否正确,这些模板参数不是可推导出的吗?如果是肯定的,为什么?
【问题讨论】:
-
闭包类型的apply操作符是
template<class T> decltype(auto) operator() (T)这样的函数模板,它不能只为id-expressionf推导类型。您可以将f包装在 lambda 中,[](auto const& t){ return f(t); } -
一个完美的转发 lambda-wrapper 来传递一个重载集对于 C++14 的多态 lambdas 非常有用。不幸的是,这是一些没有宏的样板:
#define LAMBDA_WRAP(FUN) ([](auto&&... args){ return FUN(std::forward<decltype(args)>(args)...); }) -
@dyp 为什么
()在 lambda 周围? -
@Yakk @dyp 两个连续的左方括号标记(例如,下标表达式中的 lambda-introducer)被解析为引入属性;见 dcl.attr.grammar/6。此外,
delete关键字后面的空 lambda-introducer 必须用括号括起来,否则将被解析为delete[];见 expr.delete/1。 -
@ecatmur 下标可能会破坏其他工作代码——
array[LAMBDA_WRAP(f)]——这是对宏的有效使用(将重载集对象传递给下标运算符,例如用于切片目的)。另一个,没那么多(有效)。 (你不应该直接调用LAMBDA_WRAP(f),你应该只在将f本身作为参数传递给某事物时使用它)
标签: c++ templates tuples monads c++14