[英]If classes generated from lambda expression do not have default ctor then how can an object of that generated class type be created
I am learning C++ using the resource listed here .我正在使用此处列出的资源学习 C++。 In particular, i read about lambda expressions in C++ Primer by Lippman.
特别是,我在 Lippman 的 C++ Primer 中阅读了lambda 个表达式。 There i came to know that lambdas are function objects.
在那里我知道 lambda 是 function 个对象。 Moreover, classes generated from lambda expressions do not have a default constructor .
此外,从 lambda 表达式生成的类没有默认构造函数。 So take for example:
举个例子:
auto wc = find_if(words.begin(), words.end(),
[sz](const string &a){
return s.size() >= sz;
};
It is written that the above lambda expression will generate a class that will look something like:据记载,上面的 lambda 表达式将生成一个 class,它看起来像这样:
class SizeComp {
SizeComp(size_t n): sz(n) { } // parameter for each captured
variable
// call operator with the same return type, parameters, and body as the lambda
bool operator()(const string &s) const
{ return s.size() >= sz; }
private:
size_t sz; // a data member for each variable captured by value
};
So what happens is that an unnamed object of this compiler generated class is created and is passed as the third argument to the std::find_if
shown above.因此,会发生一个未命名的 object 这个编译器生成的 class 被创建并作为第三个参数传递给上面显示的
std::find_if
。 I can understand this.我能理解这一点。
Now it is my thinking/understanding that since this compiler generated class has no default ctor, so the third argument that is passed to the std::find_if
must not be created using a default ctor since that would fail.现在我的想法/理解是,由于此编译器生成的 class 没有默认构造函数,因此不能使用默认构造函数创建传递给
std::find_if
的第三个参数,因为那样会失败。 So, internally the object that is passed should be created using the parameterized ctor something like:因此,在内部传递的 object 应该使用参数化的 ctor 创建,例如:
auto wc = find_if(words.begin(), words.end(), SizeComp(sz)); //note the third argument uses the parameterized ctor
My first question is that since there is no default ctor in case of an empty capture list in C++11 , so how will an object of that compiler generated class be created.我的第一个问题是,由于在 C++11中捕获列表为空的情况下没有默认构造函数,因此将如何创建该编译器生成的 object class。 I mean in case of an empty capture list, there will be no data members inside the compiler generated class so there will be no parameterized ctor.
我的意思是,在捕获列表为空的情况下,编译器生成的 class 中不会有数据成员,因此不会有参数化构造函数。 Which means that this compiler generated class has neither default nor parameterized ctor.
这意味着此编译器生成的 class 既没有默认构造函数也没有参数化构造函数。 Then how can an object of this class be generated.
那么这个class的一个object怎么生成呢。 For example, the situation shown below won't work when the capture list is empty:
例如,当捕获列表为空时,如下所示的情况将不起作用:
auto wc = find_if(words.begin(), words.end(),
[](const string &a){ //NOTE THE CAPTURE LIST IS EMPTY
return s.size() >= 5;
};
Now, how will the third argument to std::find_if
be created:现在,如何创建
std::find_if
的第三个参数:
auto wc = find_if(words.begin(), words.end(), CompGeneratedClass()); //this can't work because there is no default ctor
I also know that for a normal/ordinary user-defined class if we provide a user-defined ctor, then the compiler will not generate a default ctor for that class. So, it seems to me that since in case of an empty capture list lambda expression there is no user-defined ctor, the compiler should generate a default ctor for this compiler generated class. But the C++ standard says that there won't be a default ctor.我也知道,对于普通/普通用户定义的 class,如果我们提供用户定义的 ctor,那么编译器将不会为该 class 生成默认的 ctor。所以,在我看来,因为在捕获列表为空的情况下lambda 表达式没有用户定义的构造函数,编译器应该为此编译器生成一个默认构造函数 class。但是 C++ 标准说不会有默认构造函数。 So my second question is that why does this compiler generated class has different behavior than an user-defined class.
所以我的第二个问题是为什么这个编译器生成的 class 与用户定义的 class 有不同的行为。
Also, note that this explanation is not only limited to C++ Primer by Lippman.另外,请注意,此说明不仅限于 Lippman 的 C++ Primer。 I've seen the same explanation in CppCon presentations as well.
我也在CppCon演示文稿中看到了相同的解释。
The problem here is that of frame of mind.这里的问题是心态。 While the Primer is explaining the behavior in ways that one could easily understand, it is not to be taken literally.
虽然 Primer 正在以人们容易理解的方式解释行为,但不要从字面上理解。 The normative text describes behavior, not ways to achieve it.
规范文本描述的是行为,而不是实现它的方法。 A compiler doesn't actually need to create a class the same way we do.
编译器实际上不需要像我们一样创建 class。
For instance, a vendor can always sneak in some secret tag into the constructor's parameter list.例如,供应商总是可以在构造函数的参数列表中加入一些秘密标签。 Imagine this is what it generates:
想象一下,这是它生成的:
struct __secret_tag_at_src_line{};
struct __lambda_at_src_line{
__lambda_at_src_line(__secret_tag_at_src_line, /*Other arguments*/)
// ...
};
// ...
auto wc = find_if(words.begin(), words.end(), __lambda_at_src_line(__secret_tag_at_src_line{}, ...)};
We can't name that tag or even know of its existence, so we can't create the lambda on another line.我们不能命名那个标签,甚至不知道它的存在,所以我们不能在另一行创建 lambda。 And the class will never have a default constructor.
而 class 永远不会有默认构造函数。 That's a way to do it.
这是一种方法。 But even then, a compiler doesn't have to do that.
但即便如此,编译器也不必这样做。
The implementation is not bound by the same rules as us;实施不受与我们相同的规则约束; the standard gives great leeway to implementations, so long as the program is translated correctly.
该标准为实现提供了很大的回旋余地,只要程序被正确翻译即可。 A compiler could just bless a byte and say "this is a lambda", no need to call a constructor.
编译器可以只祝福一个字节并说“这是一个 lambda”,不需要调用构造函数。 Why?;
为什么?; Because it accomplishes what the standard says, the observable behavior is intact (think about it? can the initialization of a capture-less lambda be observed by a C++ program?)
因为它完成了标准所说的,可观察到的行为是完整的(想想看?C++ 程序可以观察到无捕获 lambda 的初始化吗?)
Sometimes implementations need to "cheat";有时实现需要“作弊”; heck, it's been known that implementations will call private constructors to get the job done .
哎呀,众所周知,实现将调用私有构造函数来完成工作。 But it's not really cheating, because the same rules do not apply.
但这并不是真正的作弊,因为同样的规则并不适用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.