I'm trying to get along with std::function
. From reference here one can see that argument to std::function
's ctor should be callable and copy constructible. So here is small example:
#include <iostream>
#include <type_traits>
#include <functional>
class A {
public:
A(int a = 0): a_(a) {}
A(const A& rhs): a_(rhs.a_) {}
A(A&& rhs) = delete;
void operator() ()
{
std::cout << a_ << std::endl;
}
private:
int a_;
};
typedef std::function<void()> Function;
int main(int argc, char *argv[])
{
std::cout << std::boolalpha;
std::cout << "Copy constructible: "
<< std::is_copy_constructible<A>::value << std::endl;
std::cout << "Move constructible: "
<< std::is_move_constructible<A>::value << std::endl;
//Function f = A();
return 0;
}
We have callable, copy constructible but not move constructible class. As I believe this should be sufficient to wrap it in Function
. But if you uncomment commented line compiler becomes very upset about deleted move constructor. Here is ideone link. GCC 4.8.0 doesn't compile this too.
So, is it something I misunderstand about std::function
or is it GCC's incorrect behaviour?
GCC and Clang are correct.
§17.6.3.1.1 Template argument requirements [utility.arg.requirements]
Table 20 — MoveConstructible requirements [moveconstructible].
- T u = rv; u is equivalent to the value of rv before the construction.
- T(rv); T(rv) is equivalent to the value of rv before the construction.
Table 21 — CopyConstructible requirements (in addition to MoveConstructible) [copyconstructible].
- T u = v; the value of v is unchanged and is equivalent to u.
- T(v); the value of v is unchanged and is equivalent to T(v).
Note the:
CopyConstructible requirements (in addition to MoveConstructible)
I.e. if something is CopyConstructible it must also be MoveConstructible. Though it is fine to implement the move as a copy.
Update:
Though I find it interesting that the C++11 standard doesn't seem to define is_copy_constructible
in terms of CopyConstructible, i.e. they are not quite the same, is_copy_constructible
is more relaxed as it only requires:
§20.9.4.3 Type properties [meta.unary.prop]
Table 49 — Type property predicates
- is_copy_constructible<T>; is_constructible<T,const T&>::value is true.
You misunderstood the purpose of the delete specification. A move-constructor is not default-implemented. If you try to move an object without a move-ctor it will just be copied. If you specify the move-constructor as deleted it will try to call it and then see it's deleted. That means: You cannot copy a temporary object. Remove the move-constructor statement and it will work.
Edit - Clarification:
If no move-constructor is declared(where =delete is a declaration), then a construction from a temporary object will call the copy-constructor (from const reference). If you declare a move constructor a construction from a temporary object will try to call this. So if you declare a move-ctor deleted, it will try to call a delete function, which will result in an error. If you do not declare it, it will result in a call of the copy ctor.
That's why your example doesn't work, if you wouldn't have declared it std::function would just use the copy-ctor.
By default I meant: implemented if not declared, as it happens with the copy- or default-ctor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With