C++ vector::push_back using default copy constructor - c++

I have a class (Uniform) that has a constructor with 2 parameters, and a default copy constructor (it only contains int, floats, a std::vector and a std::map). I created a
std::vector<Uniform> uniforms
that I want to fill using the
uniforms.push_back()
line. I use this code to do that (the 2nd line is just here to test the copy constructor, as it currently fails)
Uniform uni(uniform_name,type);
Uniform uni2=uni;
uniforms.push_back(uni2);
The default constructor works fine, the "uni2=uni" compiles without problem (so the default copy constructor is OK too), but the push_back returns (using g++ as a compiler):
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/ext/new_allocator.h:108:9: erreur: no matching function for call to ‘Uniform::Uniform(const Uniform&)’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/ext/new_allocator.h:108:9: note: candidates are:
./inc/uniform.h:16:5: note: Uniform::Uniform(std::string, Uniform_Type)
./inc/uniform.h:16:5: note: candidate expects 2 arguments, 1 provided
./inc/uniform.h:14:7: note: Uniform::Uniform(Uniform&)
./inc/uniform.h:14:7: note: no known conversion for argument 1 from ‘const Uniform’ to ‘Uniform&’
Thanks :)

When you say "default copy constructor" (which generally makes little sense), I assume you mean "implicitly-declared copy constructor" or "compiler-provided copy constructor"
The exact signature of the compiler-provided copy constructor will depend on the contents of your Uniform class. It could be Uniform::Uniform(const Uniform &) or Uniform::Uniform(Uniform &) depending, again, on the details of Uniform (which you didn't provide).
For example, if your Uniform includes a subobject (base or member) of type T, whose copy constructor is declared as T::T(T &) (no const), then Uniform's implicit constructor will also be implicitly declared as Uniform::Uniform(Uniform &) (no const).
A full specification can be found in the language standard (12.8/5)
The implicitly-declared copy
constructor for a class X will have
the form
X::X(const X&)
if
— each
direct or virtual base class B of X
has a copy constructor whose first
parameter is of type const B& or const
volatile B&, and
— for all the
nonstatic data members of X that are
of a class type M (or array thereof),
each such class type has a copy
constructor whose first parameter is
of type const M& or const volatile
M&.
Otherwise, the implicitly
declared copy constructor will have
the form
X::X(X&)
An
implicitly-declared copy constructor
is an inline public member of its
class.
The push_back implementation needs Uniform::Uniform(const Uniform &), but something in your class causes it to be Uniform::Uniform(Uniform &). Hence the error. There's no way to say what it is without seeing the definition of your Uniform.

Your copy constructor needs to take its argument as a const reference:
Uniform::Uniform(const Uniform& other)

Your copy constructor should accept const Uniform& and not Uniform& as the one you have does.

You failed to include the copy constructor (sic!!!) but you must have defined it wrongly:
Uniform::Uniform(Uniform&)
{
....
}
should be (note the const)
Uniform::Uniform(const Uniform&)
{
....
}

Related

Why is it impossible to explicitly default a copy constructor with volatile argument?

I could not find where in the standard it is stated that it is forbidden to explicitly default a copy-constructor and copy-assignment with a volatile& or const volatile& argument, like this:
struct A{
A(const volatile A&) =default; // fails to compile on (all) compilers
};
In [dcl.fct.def.default] there is no such a restriction, while [class.copy] specifies that A(const volatile A&) is a copy constructor.
Note: I am just looking for the location in the text of the standard which specifies this behavior.
You are in the right sections, but are overlooking some crucial bullets.
[dcl.fct.def.default]/1:
A function definition of the form:
...
is called an explicitly-defaulted definition. A function that is
explicitly defaulted shall
have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy
constructor or copy assignment operator, the parameter type may be
“reference to non-const T”, where T is the name of the member
function's class) as if it had been implicitly declared, and
[class.copy.ctor]/7:
The implicitly-declared copy constructor for a class X will have the
form
X::X(const X&)
if each potentially constructed subobject of a class type M (or array
thereof) has a copy constructor whose first parameter is of type const
M& or const volatile M&.119 Otherwise, the implicitly-declared copy
constructor will have the form
X::X(X&)
...
119) This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue;
When the above is summed up, your only two options for explicitly defaulting a copy c'tor are these:
struct A {
A(const A&) = default;
};
struct B {
B(B&) = default;
};
When the standard says A(const volatile A&) is a copy constructor. It means that a user-provided c'tor with such a parameter can be the classes copy c'tor.

Template "copy constructor" does not prevent compiler-generated move constructor

Consider the following program and the comments in it:
template<class T>
struct S_ {
S_() = default;
// The template version does not forbid the compiler
// to generate the move constructor implicitly
template<class U> S_(const S_<U>&) = delete;
// If I make the "real" copy constructor
// user-defined (by deleting it), then the move
// constructor is NOT implicitly generated
// S_(const S_&) = delete;
};
using S = S_<int>;
int main() {
S s;
S x{static_cast<S&&>(s)};
}
The question is: why does not user-defining the template constructor (which effectively acts as a copy constructor when U = T) prevent the compiler from generating the move constructor, while, on the contrary, if I user define the "real" copy constructor (by deleting it), then the move constructor is not generated implicitly (the program would not compile)? (Probably the reason is that "template version" does not respect the standard definition of copy-constructor also when T = U?).
The good thing is that that seems to apparently be what I want. In facts, I need all the copy and move constructors and all the move and copy assignment operators that the compiler would generate implicitly as if S was simply defined as template<class U> S{}; plus the template constructor for the conversions from other S<U>. By standard, can I rely on the above definition of S to have all the mentioned stuff I need? If yes, I could then avoid to "default'ing" them explicitly.
The answer is simple - There is no (!) template copy constructor. Even if the template parameter matches the parameter of a copy constructor it is no copy constructor.
See 12.8 Copying and moving class objects
A non-template constructor for class X is a copy constructor if its
first parameter is of type X&, const X&, volatile X& or const volatile
X&, and either there are no other parameters or else all other
parameters have default arguments (8.3.6). [ Example: X::X(const X&)
and X::X(X&,int=1) are copy constructors.
Similar applies to the move constructor
There is no such thing as a templated copy constructor. The regular (non-templated) copy constructor is still generated and a better match than the templated one with the signature you provided (things get more complicated with "universal" references thrown in the mix, but that is off-topic).
Copy constructors, and move constructors, are not templated. The C++ standard is specific on what constitutes a copy constructor.
From: http://en.cppreference.com/w/cpp/language/copy_constructor
A copy constructor of class T is a non-template constructor whose first parameter is T&, const T&, volatile T&, or const volatile T&, and either there are no other parameters, or the rest of the parameters all have default values.

Conversion by constructors

Class X -> converted to Y by two ways 1) constructors, and 2) by conversion functions.
I understood the single argument constructor is used for conversion.
In the specification:
An implicitly-declared copy constructor is not an explicit constructor; it may be called for implicit type conversion.
Question:
So, that means not only single argument constructor is used for the conversion, but also copy constructor?. If so, which scenario it is used?. any snippet of sample code?
Kindly bear with me if the question is very basis.
Copy constructor is not an explicit constructor, so it will be used wherever possible. Copy constructor will "convert" only from the same type, so it is not a conversion in the full sense. However, for the sake of generality it is handy to call it one.
Read this paper: http://www.keithschwarz.com/cs106l/winter20072008/handouts/180_Conversion_Constructors.pdf if you want more details on conversion constructors.
It basically means that you can do:
struct A {};
A a;
A b = a;
If the copy constructor was marked explicit that would fail to compile. You can test it by adding: explicit A( A const & ) {} to the struct and recompiling the program.
Implicitly-declared copy constructor cannot use for conversions, since it's copy-ctor, that has declared as T(const T&) or T(T&).
draft n3337 par 12.8 C++ standard.
8 The implicitly-declared copy constructor for a class X will have the
form X::X(const X&) if — each direct or virtual base class B of X has
a copy constructor whose first parameter is of type const B& or const
volatile B&, and — for all the non-static data members of X that are
of a class type M (or array thereof), each such class type has a copy
constructor whose first parameter is of type const M& or const
volatile M&.119 Otherwise, the implicitly-declared copy constructor
will have the form X::X(X&)
Since copy c-tor is not explicit you can use such code
struct So
{
};
int main()
{
So s = So();
}
If copy-ctor is explicit you could use only initizaliation like So s((So()));
An implicit copy constructor is one that the compiler writes for you. It always has the form
T(const T&);
This means that any object which has a conversion operator to const T& can be implicitly copied, even if this isn't what you wanted. The most common way to trigger this is to make a copy to a base class from a derived class; this is called object slicing because the copy won't have the same type as the original and will probably lose some important properties or behavior.

Copy constructor with 2 argument

class Sample
{
public:
Sample(){}
Sample(const Sample& obj){ cout<<"C.C. with 1 argument called"<<endl;}
Sample(const Sample& obj, int i){ cout<<"C.C. with 2 arguments called"<<endl;}
};
void main()
{
Sample s1;
Sample s2 = s1; // Here, C.C with 1 arg. called.
}
There are few questions:
How I can make a call to copy constructor having 2 arguments?
When we require a copy constructor with 1 argument and when we require C.C with 2 argument?
A constructor with 2 (or more) required arguments is not a copy constructor.
1.:
Sample s2(s1, 0);
Just to add little formalism here. Standard has strict definition for "Copy constructor" term (12.8 ):
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other parameters
have default arguments (8.3.6). [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.
A class will only really have one copy ctor, which can be invoked with only one argument. It can take two (or more) arguments, but only if it provides default values for the other arguments. Either way, the first argument must be a (normally const) reference to an object of the same type.
Your second ctor taking two arguments isn't really a copy ctor (at least as the term is normally used) -- it's just a ctor that happens to take an instance as an argument (may base the new instance on that argument, at least in part).

Which constructor is invoked here?

In this code fragment, which constructor is actually called?
Vector v = getVector();
Vector has copy constructor, default constructor and assignment operator:
class Vector {
public:
...
Vector();
Vector(const Vector& other);
Vector& operator=(const Vector& other);
};
getVector returns by value.
Vector getVector();
Code uses C++03 standard.
Code fragment looks like it is supposed to call default constructor and then assignment operator, but I suspect that this declaration is another form of using copy constructor. Which is correct?
When = appears in an initialization, it calls the copy constructor. The general form is not exactly the same as calling the copy constructor directly though. In the statement T a = expr;, what happens is that if expr is of type T, the copy constructor is called. If expr is not of type T, then first an implicit conversion is done, if possible, then the copy constructor is called with that as an argument. If an implicit conversion is not possible, then the code is ill-formed.
Depending upon how getVector() is structured, the copy may be optimized away, and the object that was created inside the function is the same physical object that gets stored in v.
Assuming that you haven't done something pathological outside of the code you are showing, your declaration is a copy-initialization, and the second part of this rule applies:
13.3.1.3 Initialization by constructor [over.match.ctor]
1 When objects of class type are direct-initialized (8.5), or copy-initialized from an
expression of the same or a derived class type (8.5), overload resolution selects the
constructor. For direct-initialization, the candidate functions are all the constructors
of the class of the object being initialized. For copy-initialization, the candidate
functions are all the converting constructors (12.3.1) of that class. The argument
list is the expression-list within the parentheses of the initializer.
For a simple test case, see Eli Bendersky's post, here: http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/
Always remember the rule:
Whenever, an object is being created and given some value in the same single statement then it is never an assignment.
To add Further,
Case 1:
Vector v1;
Vector v(v1);
Case 2:
Vector v = getVector();
In the above two formats Case 1 is Direct Initialization while Case 2 is known as Copy Initialization.
How does Copy Initialization work?
Copy initialization constructs an implicit conversion sequence: It tries to convert return value of getVector() to an object of type Vector. It can then copy the created object into the object being initialized, So it needs a accessible copy constructor.
The copy constructor actually gets elided in this case (check this) and just the default constructor ends up getting called
EDIT:
The constructor is only sometimes elided, as per Benjamin's answer. For some reason I read that as you calling the constructor directly.