When I try the following code in GCC 6.3 (ideone.com), it compiles and prints "OK!". When I try the same code in C++ Builder 10.1, it fails to compile:
[bcc32c Error] tuple(110): no matching constructor for initialization of 'A'
tuple(433): in instantiation of function template specialization 'std::_Tuple_val<A>::_Tuple_val<std::_Tuple_val<A> >' requested here
File3.cpp(4): candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::_Tuple_val<A>' to 'const A' for 1st argument
File3.cpp(4): candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
Line 433 is tuple(_Myt&&) = default;
.
#include <iostream>
#include <functional>
struct A {
// Define destructor to delete default move constructor
~A() {}
int a = 0;
};
void func(const A&)
{
std::cout << "OK!" << std::endl;
}
int main() {
A a;
auto f = std::bind(&func, a);
f();
}
In the code, I define destructor in class A so that no move constructor is implicitly defined. The class should still have implicitly defined default constructor and copy constructor. Documentation says "The arguments to bind are copied or moved", so I expected that having a copy constructor is enough for using bind.
What explains this difference between two compilers? It this implementation-defined behavior or am I using std::bind incorrectly here?
C++ Builder is using C++11 and Ideone is C++14, so could that explain the difference?
std::bind should copy all CopyConstructible parameters into its return value:
The return type of std::bind holds a member object of type std::decay::type constructed from std::forward(f), and one object per each of args..., of type std::decay::type, similarly constructed from std::forward(arg_i).
In this test case, it should be unnecessary for move constructors to be invoked. This looks like a bug in C++ Builder. I have filed a bug report: https://quality.embarcadero.com/browse/RSP-20209