Default constructor prevents from calling emplace_back - c++

It seems that adding a default constructor prevents from calling emplace_back and produces the error message: "static assertion failed: type is not assignable" (gcc 5.3 with -std=c++14). Here is a simple code that illustrates the issue:
class A {
public:
int a;
A() = default;
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error: type is not assignable
return 0;
}
When removing the default constructor, the error goes away! Also, if the default constructor is defined (even if it does nothing), the error also goes away:
class A {
public:
int a;
A() {
}
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A b;
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error gone
return 0;
}
It seems that "A() = default;" is what is causing the problem.
Is this normal behaviour on part of the compiler or is it a bug?

It's a libstdc++ bug (edit: reported as bug 69478).
Briefly, libstdc++'s std::vector, as relevant here, uses std::uninitialized_copy (paired with move iterators) to move elements on reallocation, which is reduced to std::copy if the type is trivial and the iterators' reference types are assignable (i.e., the assignment operator that would conceptually be used is usable).
Then, the std::copy for pointers to trivial types (or in our case, a move_iterator wrapping a pointer) is in turn optimized into a call to memmove coupled with a check for is_copy_assignable. Of course, that check is wrong in this case, since the uninitialized_copy, paired with move iterators, only requires the thing to be move constructible.
When you don't have a default constructor or if the default constructor is user-defined, then the class isn't trivial, so you don't hit the code path that triggers this bug.

Related

warning: definition of implicit copy constructor even though I didn't call copy constructor

I am trying to run this example in https://en.cppreference.com/w/cpp/language/copy_assignment, but when I delete the default constructor and default copy constructor: A() = default; A(A const&) = default;, clang++ says that warning: definition of implicit copy constructor for 'A' is deprecated because it has a user-provided copy assignment operator [-Wdeprecated-copy-with-user-provided-copy].
My question is that I have called copy assignment instead of copy constructor, why clang++ reports copy constructor warning?
Here is my code:
#include <iostream>
#include <memory>
#include <string>
#include <algorithm>
struct A
{
int n;
std::string s1;
// user-defined copy assignment (copy-and-swap idiom)
A& operator=(A other)
{
std::cout << "copy assignment of A\n";
std::swap(n, other.n);
std::swap(s1, other.s1);
return *this;
}
};
int main()
{
A a1, a2;
std::cout << "a1 = a2 calls ";
a1 = a2; // user-defined copy assignment
}
Here is cppinsight link, I can see there is an inline copy constructor in struct A.
struct A
{
int n;
std::basic_string<char> s1;
inline A & operator=(A other)
{
std::operator<<(std::cout, "copy assignment of A\n");
std::swap(this->n, other.n);
std::swap(this->s1, other.s1);
return *this;
}
// inline A(const A &) noexcept(false) = default;
// inline ~A() noexcept = default;
// inline A() noexcept = default;
};
This invokes A's copy constructor since other is a value copy.
inline A & operator=(A other)
Change it to
inline A & operator=(const A& other)
Then drop the swaps and simply assign other's member variables to *this
n=other.n;
s1=other.s1;
This removes the requirement for a copy constructor. However, defining an assignment operator w/o also defining a copy constructor violates the rule of three hence the compiler warning. Also, "inline" is intrinsic when the member function is defined in the class.

std::swap between std::shared_ptr<A> where A has dynamic array

first, my code:
struct A {
A(int size);
~A();
A(A&& other);
A& operator=(const A& other);
uint8_t* data = nullptr;
};
A::A(int size)
{
data = new uint8_t[size];
}
A::~A()
{
delete [] data;
data = nullptr;
}
A::A(TPixel &&other)
{
data = other.data;
}
A& A::operator=(const A& other)
{
data = other.data;
}
I have two variable
std::shared_ptr<A> a = std::make_shared<A>(5);
std::shared_ptr<A> b = std::make_shared<A>(5);
I tried std::swap(a, b);
and found error in valgrind:
std::enable_if<std::__and_<std::is_move_constructible<A*>, std::is_move_assignable<A*> >::value, void>::type std::swap<A*>(A*&, A*&)
Why I get this error?
I have implemented move operators and when I tested std::is_move_assignable and std::is_move_constructible the return value was true.
found error in valgrind:
std::enable_if<std::__and_<std::is_move_constructible<A*>, std::is_move_assignable<A*> >::value, void>::type std::swap<A*>(A*&, A*&)
Why I get this error?
What you show is not an error. It is a function declaration.
I have implemented move operators
You have not implemented a move assignment operator.
P.S.
You haven't defined the move constructor.
You have defined a constructor that you didn't declare: A::A(TPixel &&). This may be related.
The copy assignment operator
leaks memory.
leaves both objects pointing to the same array.
The destructor has undefined behaviour if the object has been copy-assigned and the copy has already been destroyed.

overloading operator = for casting

As title, can be to overloading operator = for casting?
I have a simple class.
class A{
protected:
int m_int;
public:
A& operator=( int& obj)
{
m_int = obj;
return *this;
}
};
I want:
A t_a = 1;
and
int t_int = t_a;
Is there a way to do this?
Just define conversion operator
operator int() const
{
return m_int;
}
or
explicit operator int() const
{
return m_int;
}
In the last case you have to use an explicit casting in the statement
int t_int = int( t_a );
Take into account that the assignment operator should be declared like
A& operator=( const int& obj)
{
m_int = obj;
return *this;
}
or like
A& operator=( int obj)
{
m_int = obj;
return *this;
}
Otherwise it will be impossible to bind the non-constant reference with integer literals or temporary values.
As for the assignment operator then you may define only a compound assignment operator for the type int and the type A.
For example you could define the operator += or something other operator.
Yes, that’s possible. You need a custom ctor and assignment operator. But writing those disables some of the compiler generated ctors/assignment ops. If you still need/want them, you need to reintroduce them explicitly.
class A
{
protected:
// Note the initializer. Without it m_int is uninitialized
// when you default construct an A. That’s a common source
// of bugs.
int m_int = 0;
public:
// Following two are the important ones
A(int i) : m_int(i) {}
A& operator=(int i)
{
m_int = i;
return *this;
}
// if A needs to be default constructible as well
A() = default;
// The int ctor/assignment disable the compiler generated
// normal copy ctor/assignment (the ones that take another A).
// Reintroduce them like this:
A(const A&) = default;
A& operator=(const A&) = default;
// Writing any copy ctor/assignment disables the compiler generated
// move ctor/assignment. If you still want them, reintroduce them.
A(A&&) = default;
A& operator=(A&&) = default;
};
A t_a = 1;
This doesn't use assignment. You need a constructor which takes an int argument.
int t_int = t_a;
You will need operator int() for this.
Note that it is a really bad idea to have a class which has both an implicit constructor from a type, and an implicit cast to the type. You will get all sorts of confusing errors when you try to do overload resolution.
Instead, I would make the constructor explicit, and write an explicit conversion function. That means you have to write:
int t_int = t_a.to_int();
But at least it's explicit.
Edit: Note that you can overload operator = for casting (either inside or outside the class), but neither of the code samples you gave will use it. = is used both for assignment and initialization, and both your samples are initialization (so won't use operator =)

Return a copy from a function of a non moveable object

A friend of mine stumbled on a question
Is there any way to return a copy of an object which is copy-able but NOT move-able. In other words, can we make the following code work?
struct A {
A() = default;
A(A const&) = default; // copyable
A& operator=(A const&) = default; // assignable
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A() = default;
};
A foo() {
A a;
return a;
}
int main() {
A a(foo()); //will fail, because it calls A(A&&)
return 0;
}
In my opinion, we can't, because foo() is an A&& an then the compiler has to call A(A&&). But I would like some kind of confirmation.
Following on from the code in the posted comment by dyp; Is there a cast (or standard function) with the opposite effect to std::move?, the following code snippet compiles.
I'm not sure on the usefulness of the code, there was some discussion on whether this was a good idea or not in that linked post.
struct A {
A() = default;
A(A const&) = default; // copyable
A& operator=(A const&) = default; // assignable
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A() = default;
};
template <typename T>
T& as_lvalue_ref(T&& t) {
return t;
}
A foo() {
A a;
return as_lvalue_ref(a);
}
int main() {
A a(as_lvalue_ref(foo()));
return 0;
}
Code sample here.
A static_cast<T&>() would also work in place of the as_lvalue_ref() and may even be preferable (although looking clumsy) given that it is in fact verbose. In any situation where a reference is returned, dangling references can happen. Given the signature A foo() in this case (instead of say A& foo()), there are no dangling references here, a full object of A returned. The line A a(as_lvalue(foo())); has no dangling references either since the temporary (prvalue) returned from as_lvalue_ref(foo()) remains valid until the end of the expression (;) and then the a object will be then well formed.
Someone came up in another forum with that code. It should not lead to potential dangling references, which may be the case with Niall's code. But is still convoluted for something that was legal in C++03
#include <iostream>
#include <functional>
struct A {
A() =default;
A(A const& a)=default;
A& operator=(A const& a)=default;
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A()=default;
int n;
};
A foo(void) {
A a;
a.n=5;
std::cout<<"&a="<<&a<<std::endl;
return std::cref(a); // A(A const&)
// ~A()
}
int main(void) {
A b; // A()
std::cout<<"&b="<<&b<<std::endl;
A const& const_ref_to_temp=foo(); // OK in C++
b= const_ref_to_temp; //A=A const& [OK]
std::cout<< b.n<<std::endl;
return 0;
}

Initializer lists: copy constructors and assignment operators = redundancy?

It seems that initalizer lists are a good idea for your class constructors and, I'm assuming, for the copy constructor as well. For the assignment operator one has to assign each member in the body of the function. Consider the following simple block:
class Foo {
private:
int a,b;
public:
Foo(int c, int d) : a(c), b(d) {}
Foo(const Foo & X) : a(X.a), b(X.b) {}
Foo& operator=(const Foo& X) {
if (this == &X) return *this;
a = X.a;
b = X.b;
return *this;
}
};
If a class has a moderate amount of data members, there are three places where one can mess up the the different assignments/initialization. By that I mean, what if the copy constructor looked like:
Foo(const Foo & X) : a(X.a), b(X.a) {}
or a line was missing from the operator=. Since the assignment operator and the copy constructor often have the same effect (in that we copy members from one Foo to another) can I "reuse" the code from the copy constructor or the assignment operator or vice versa?
Your goal should be to not write copy constructors/assignment operators at all. Your goal should be to let the compiler do it. Standard library containers are all copyable, so use them where reasonable.
If there are members that cannot be copied correctly, then use smart pointers or other RAII objects. Those objects are the ones that should need special copy constructors/assignments. And they only need them for their one member.
Everything else should not use them.
Since the assignment operator and the copy constructor often have the same effect.
Not at all, one does initialization while the other does assignment. They are different in the initial state of the object, and their tasks are separate (though similar). The canonical assignment operator is usually done as:
Foo& operator=(Foo right) {
right.swap( *this );
return *this;
}
It might not be valid to forward all to an assignment operator, but that is was commmon in C++03 where it was allowed.
In C++11 constructors are easier: forward all the constructors to one master constructor.
class Foo {
private:
int a,b;
public:
Foo(int c, int d) : a(c), b(d) {}
Foo(const Foo & X) : Foo(x.a, x.d) {}
//syntax may be wrong, I don't have a C++11 compiler
Foo& operator=(const Foo& X) {
if (this == &X) return *this;
a = X.a;
b = X.b;
return *this;
}
}
In C++03 (where it is allowed)
class Foo {
private:
int a,b;
void init(int c, int d) {a=c; b=d;}
public:
Foo(int c, int d) : {init(c,d);}
Foo(const Foo & X) : {init(X.a, X.b);}
Foo& operator=(const Foo& X) { init(X.a, X.b);}
}
But keep in mind that this cannot be used in some common cases. (any object that isn't assignable)