Copy constructor with 2 argument - c++

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).

Related

What is the meaning of ellipses in a copy constructor?

Consider the following program:
#include <iostream>
struct Test
{
int a;
Test() : a(3)
{ }
Test(const Test& t...)
{
std::cout<<"Copy constructor called\n";
a=t.a;
}
int get_a()
{
return a;
}
~Test()
{
std::cout<<"Destructor is called\n";
}
};
int main()
{
Test t;
Test* t1=new Test(t);
std::cout<<t.get_a()<<'\n';
std::cout<<t1->get_a()<<'\n';
delete t1;
}
Closely observe the three dots in parameter of copy constructor
I was really surprised when I tried this program. What is the use of it? What does it mean?
What the language specification says about this?
I know that three dots are used to represent variable length arguments in variadic functions
like printf() and scanf() etc and also variadic macros introduced by C99. In C++, if I am not wrong, they are used in variadic templates.
Is this code well formed? Is this variadic copy constructor that can take any number of arguments?
It compiles & runs fine on g++ 4.8.1 & MSVS 2010.
The draft standard in section 8.3.5 [dcl.fct] says , ... is synonymous with ... unless ... is part of abstract-declarator (emphasis mine):
[...]If the parameter-declaration-clause terminates with an ellipsis
or a function parameter pack (14.5.3), the number of arguments shall
be equal to or greater than the number of parameters that do not have
a default argument and are not function parameter packs. Where
syntactically correct and where “...” is not part of an
abstract-declarator, “, ...” is synonymous with “...”.[...]
So it is a variadic function and as far as I can tell without additional arguments this is also a valid copy constructor, from section 12.8 [class.copy]:
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).
and this note says that ellipses are not parameters:
void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow
// a parameter with a default argument
which is backed up by the normative text above which says:
If the parameter-declaration-clause terminates with an ellipsis[...]
Note, since it was asked an abstract-declarator is a declarator without an identifier.
What is the use of it? What does it mean?
Yes, it introduces a variadic function.
In C++ If I am not wrong they are used in variadic templates.
The syntax and semantics are different. It's a "C-style" variadic function, not a variadic template function. A copy constructor, moreover, cannot be a template function.
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).
Per §12.8.2 in the final draft (emphasis mine)
Is this code well formed? Is this variadic copy constructor that can take any number of arguments?
If the ellipsis contains parameters, it is no more a copy constructor but a simple constructor. If there aren't, then it is a valid copy constructor.
X(const X&, int = 1, double = 5); // copy-ctor
X(const X&, int = 1, double); // constructor

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.

Why am I not provided with a default copy constructor from a volatile?

This code:
class X {
int member;
};
volatile X a;
X b = a;
Fails with the error:
prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
Is there any way I can get the compiler to generate a volatile copy constructor for me?
The short answer is: Because the standard says you won't.
The C++ Standard 12.8/9 (Draft N3242) tells:
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&. [Note: 119]
Otherwise, the implicitly-declared copy constructor will have the form
X::X(X&)
Note 119 says:
This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue;
see C.1.9.
In C.1.9 you'll find:
The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a
copy of a volatile lvalue. For example, the following is valid in ISO C:
struct X { int i; };
volatile struct X x1 = {0};
struct X x2(x1); // invalid C++
struct X x3;
x3 = x1; // also invalid C++
Rationale: Several alternatives were debated at length. Changing the parameter to volatile const X& would greatly complicate the generation of efficient code for class objects. Discussion of providing two alternative signatures for these implicitly-defined operations raised unanswered concerns about creating ambiguities and complicating the rules that specify the formation of these operators according to the bases and members.
The key problem is that you provide no assignment constructor. Consequently, the compiler generate a default one for you:
X& X::operator =(const X& x){
this.member = x.member;
return *this;
}
The default assignment constructor accepts argument type as const X& in which the const is a low-level const and won't be ignored as top-level const.
Your code X b = a means to call the default constructor. But your argument a has type volatile X (can be converted to volatile X & and volatile const X &) cannot be converted to const X& implicitly.
So you should define your own assignment constructor as
X& X::operator =(volatile const X&);
EDIT
It shocks me that so many guys think the copy constructor (or call copy initialization) is called when using assignment operator.
Maybe call it assignment operator is not common. However, what I care is which method is called.
You can refer to this post:Copy constructors, assignment operators, and exception safe assignment and Default assignment operator
EDIT
I made a mistake previously.
X b = a is just a initialization process. No assignment is involved.
Apologize for my error message.

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.

C++ vector::push_back using default copy constructor

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&)
{
....
}