C++14 lambda 的默认参数类型推导,具体取决于前面的参数
C++14 lambda's default argument type deduction depending on preceding arguments
这对C++14无效吗?
auto f = [](auto x, auto y = std::decay_t<decltype(x)>{}) { };
f(0);
我原以为它大致相当于
auto f = [](int x, int y) { };
f(0, int{});
GCC 6.3和Clang 4.0都不接受我的代码。
- http://ideone.com/b7b4SKGCC
- http://ideone.com/EyLYaLClang
这与我对C++模板推导阶段缺乏了解有关吗?这份长达1400页的规范真的对我的问题有明确的答案吗?
更新
总之,我的问题实际上可以简化为这段代码(没有lambda,单个参数),并且在C++14下是无效的(感谢@BaummitAugen和@NirFriedman)
template <typename T>
void f(T x = 0) { }
int main() {
f();
}
编译器拒绝您的代码是正确的,它确实不是有效的C++14。
在标准中(此处使用N4141),我们有
对于泛型lambda,闭包类型具有公共内联函数调用操作员成员模板(14.5.2),其模板参数列表由一个发明的类型模板组成-lambda的参数声明子句中每次出现auto的参数,按出现顺序排列。
(5.1.2/4[expr.prim.lambda])。因此,您的调用相当于对某个的调用
template <class T1, class T2>
auto operator() (T1 x, T2 y = std::decay_t<decltype(x)>{});
现在
如果模板参数仅用于非推导上下文,并且没有明确指定,则模板参数推导失败。
(14.8.2/4[临时扣除类型])和
非推导上下文为:
[…]
-在具有默认参数的函数参数的参数类型中使用的模板参数正在进行参数推导的调用中使用的。
(14.8.2/5[temp.dexer.type])会使您的调用格式不正确。
我不能引用规范,但我会引用cppreference,它是一个权威来源,通常更容易阅读/遵循。特别是,请参见http://en.cppreference.com/w/cpp/language/template_argument_deduction.
非推导上下文
在以下情况下,用于组成p的类型、模板和非类型值不参与模板参数推导。。。
您可能已经意识到模板参数不能总是推导出来的。往下看条目列表,我们看到:
4)在函数参数的参数类型中使用的模板参数,该参数具有正在进行参数推导的调用中使用的默认参数:
它给出了以下示例:
template<typename T, typename F>
void f(const std::vector<T>& v, const F& comp = std::less<T>());
std::vector<std::string> v(3);
f(v);
可变lambdas基本上等效于函数模板,每个auto的使用都替换了一个类型模板参数,所以这个示例(不编译)等效于您的示例。
所以基本上,第二种类型是无法推导的,因为它是一个非推导的上下文。
通过给出一个很好的例子,说明为什么决定将其作为一个非推导的上下文,这个答案可能会得到改进,因为天真地认为这是可能的。我的猜测是,这基本上是因为函数模板就是创建函数的模板。反过来,默认参数本质上为同一函数创建多个可调用签名。因此,在拥有函数之前,您无法真正处理默认情况,但在实例化之前,您不能拥有函数,这需要了解模板参数。
值得注意的是,这个更简单的例子有同样的问题:
template<typename T, typename F>
void f(const std::vector<T>& v, const F& comp = int{});
因此,对第一个模板参数的依赖实际上与问题无关。
- 将强制转换简化为取决于参数的类型
- cpp 模板专用化,错误说参数 1 的类型为 T,这取决于参数 T
- 模板函数,其中模板参数类型取决于函数参数
- GCC:指定的界限取决于源参数的长度
- 具有尾随返回类型的通用 lambda,具体取决于 C++11 中的可变参数
- 类模板中的std ::数组的大小,具体取决于模板参数
- LIBELAS是否取决于相机参数
- 具有取决于模板参数的方法的模板类
- 模板层次结构中的可选虚拟函数,具体取决于参数
- 约束模板参数取决于传递的函子
- 为什么固定尺寸错误发生取决于默认参数
- C++14 lambda 的默认参数类型推导,具体取决于前面的参数
- 委托构造函数和默认参数,具体取决于其他参数
- 取决于参数的数量,将其返回结构对象,并将其分配给常规结构的对象
- 具有模板参数取决于参数列表
- 返回类型取决于模板参数
- 是否可以定义一个 C++11 可变参数类模板,其可变参数基数取决于整数模板参数
- 返回取决于sizeof的变量类型..参数包
- 模板化结构的友元函数,其参数类型取决于结构的内部
- 变量模板函数,其中返回类型取决于模板参数列表