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();
}
Godbolt conformance view
GCC和Clang似乎删除了复制赋值操作符。
从标准的Angular 来看,哪种编译器更正确?
2条答案
按热度按时间quhf5bfb1#
我没有标准中的确切措辞,但是编译器错误和cppreference一起给予了一个很好的概念:
根据标准,如果类实现了移动构造函数,则隐式定义的复制构造函数将被删除。如果存在默认复制构造函数,则不会删除https://en.cppreference.com/w/cpp/language/copy_constructor。
std::bind的返回类型是未指定的可复制构造类型(如果所有参数都是可复制构造的),否则是可移动构造的。https://en.cppreference.com/w/cpp/utility/functional/bind。
所以我认为所有的编译器都可以自由地使用标准中未指定的部分。
顺便说一句,我将在lambda中捕获示例,而不是使用
std::bind
。olhwl3o22#
绑定类型的行为未指定,不属于以下类型:你可以根据占位符用一组参数调用它,它是可构造/可析构的,如果所有绑定参数都是可复制的,那么它也是可复制构造的.
就是这样。没有要求类型是可复制赋值的。因此它是...未指定的。所以 * 所有的 * 都是对的。
如果您希望代码具有可移植性,就不应该依赖于未指定的行为。