Reassigning std::bind using auto: which compiler gets it right?

huangapple go评论60阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年2月24日 07:12:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定