英文:
Reassigning std::bind using auto: which compiler gets it right?
问题
MSVC编译以下代码,而GCC和Clang不编译。
#include <iostream>
#include <functional>
class Class
{
public:
void display() { std::cout << "display" << std::endl; }
void store() { std::cout << "store" << std::endl; }
};
int main()
{
Class instance;
// std::function<void(void)> f; // this will work
auto f = std::bind(&Class::display, instance);
f();
f = std::bind(&Class::store, instance);
f();
}
从标准角度来看,似乎GCC和Clang删除了复制赋值运算符。
哪些编译器在标准角度上更正确?
英文:
MSVC compiles the following code, while GCC and Clang don't.
#include <iostream>
#include <functional>
class Class
{
public:
void display() { std::cout << "display" << std::endl; }
void store() { std::cout << "store" << std::endl; }
};
int main()
{
Class instance;
// std::function<void(void)> f; // this will work
auto f = std::bind(&Class::display, instance);
f();
f = std::bind(&Class::store, instance);
f();
}
<sub>Godbolt conformance view</sub>
It seems that GCC and Clang have the copy assignment operator deleted.
Which compilers get it more correct from a standard point of view?
答案1
得分: 1
绑定类型的行为未指定,除以下情况外:您可以根据占位符调用它,并且它是可移动构造/可销毁的,如果所有绑定的参数都是可复制的,那么它也将是可复制构造的。
就是这样。不要求该类型可复制赋值。因此...未指定。所以它们全部都是正确的。
如果您希望您的代码具有可移植性,您不应依赖未指定的行为。
英文:
The behavior of the binding type is unspecified, outside of the following: you can call it with a certain set of parameters based on the placeholders, it's move constructible/destructible, and if all of the bound parameters are copyable, then it too will be copy constructible.
That's it. There is no requirement that the type is copy-assignable. It is therefore... unspecified. So all of them are right.
And if you want your code to be portable, you shouldn't rely on unspecified behavior.
答案2
得分: 1
I don't have the exact wording in the standard, but the compiler error together with cppreference give a pretty good idea of what is happening:
根据标准,如果类实现了移动构造函数,隐式定义的复制构造函数将被删除。如果存在默认的复制构造函数,它不会被删除。来源
std::bind 的返回类型是一个未指定的可复制构造类型(如果所有参数都是可复制构造的),否则是可移动构造的。来源
所以我认为所有编译器在标准的未指定部分具有自由权。
另外,我建议在 lambda 中捕获实例,而不是使用 std::bind
。
英文:
I don't have the exact wording in the standard, but the compiler error together with cppreference give a pretty good idea of what is happening:
According to the standard, the implicitly defined copy constructor is deleted, if the class implements a move constructor. If a default copy constructor exists, it will not be deleted https://en.cppreference.com/w/cpp/language/copy_constructor.
The return type of std::bind is an unspecified copy-constructible type (if all arguments are copy-constructible) and move-constructible otherwise. https://en.cppreference.com/w/cpp/utility/functional/bind.
So I suppose all compilers are correct in having freedom for the unspecified part of the standard.
On a side note, I would capture the instance in a lambda instead of using std::bind
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论