Multiple Default Constructors - c++

From this stack overflow question the answer contains this quote:
... definition says that all default constructors (in case there are multiple) ...
How can there be multiple default constructors, and why may that be useful or allowed by the standard?

Default constructors don't have to have no parameters; they just need to be invocable with no arguments.
This condition is fulfilled by any constructor whose arguments all have defaults.
[class.dtor/1]: A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters). [..]
struct Foo
{
Foo(int a = 0);
Foo(std::string str = "");
};
Now, of course, in this example you cannot actually instantiate a Foo using either of them without providing an argument (the call would be ambiguous). But Foo is still usable, and these are still "default constructors". That's just how the standard has decided to categorise things, for the purpose of defining rules. It doesn't really affect your code or programming.
(By the way, I didn't want to distract but you should have explicit on both of those!)

Here's an example of a class with two default constructors that can be default constructed:
struct Foo
{
Foo(); // #1
template <class... Args>
Foo(Args...); // #2
};
auto test()
{
Foo f{}; // ok calls #1
}

Related

Why std::optional::value_or dont have a specialization for default ctor types?

std::optional<Class> a;
a.value_or( Class() ).GetMember();
Why cant we do this like:
a.value_or().GetMember();
Can standard specialize value_or on a default constructible basis?
Unfortunately this value_or doesn't have this option and I agree with with Max Langhof's comment that it should be a separate function value_or_default.
Nevertheless, as Eljay pointed out in this comment, the code from the question might cause problems for classes with expensive default construction. In cases when the optional does not carry a value, we don't want the default constructor to be called.
I've put together a little workaround for that particular case:
struct default_constructor_t {
explicit default_constructor_t() = default;
};
inline constexpr default_constructor_t default_constructor{};
class Class {
...
Class(default_constructor_t) : Class{} {}
...
};
int GetMember(std::optional<Class> Object) {
return Object.value_or(default_constructor).GetMember();
}
In this solution, you need to add an additional implicit constructor to your class. This solution is also lazy. It will call default constructor only if optional doesn't have a value.
UPD:
After a bit of thinking, I believe that I came up with a bit more generic solution that will work even with types the developer can't modify. And even if one has this ability, less code is better, right?
struct DefaultConstructed {
template <class T> operator T() const {
return T();
}
};
constexpr DefaultConstructed Default;
class Class {
...
};
int GetMember(std::optional<Class> Object) {
return Object.value_or(Default).GetMember();
}
This solution uses conversion operator instead of implicit construction. Special object named Default can be converted (so to speak) to any type by calling this type's default constructor. It also retains the nice property of the original solution to be lazy.

C++ automatic type deduction in constructor

I am trying to understand the following code that I saw today. I already tried to find a related question, but since I have no idea what this feature of C++ is called it is hard to find related posts. A hint on the correct search term might already help me.
struct A
{ int x; };
struct B
{ B(A a) {}; };
int main()
{
B b{ { 5 } }; // works, seems to create a struct A from {5} and pass it to B's constructor
std::make_unique<B>({ 5 }); // doesn't compile
return 0;
}
Why is {5} not used to create a struct A when passed to make_unique but is used this way in the constructor of B?
If B had a second constructor B(int foo) {}; this one would be used instead of the one frome above (at least that is what I found by trial and error). What is the rule to decide if the argument is automatically used to create a struct A or if it is used directly as int in the constructor?
I am using Visual C++ 14.0
Here's a simplified demonstration:
struct X { X(int); };
void foo(X );
template <typename T> void bar(T );
foo({0}); // ok
bar({0}); // error
The issue is that braced-init-lists, those constructs that are just floating {...}s, are strange beasts in C++. They don't have a type - what they mean must be inferred from how they're actually used. When we call foo({0}), the braced-init-list is used to construct an X because that's the argument - it behaves as if we wrote X{0}.
But in bar({0}), we don't have sufficient context to know what to do with that. We need to deduce T from the argument, but the argument doesn't have a type - so what type could we possibly deduce?
The way to make it work, in this context, is to explicitly provide that T:
bar<X>({0}); // ok
or provide an argument that has a type that can be deduced:
bar(X{0}); // ok
In your original example, you can provide the A directly:
make_unique<B>(A{5})
or the B directly:
make_unique<B>(B({5}))
or just use new:
unique_ptr<B>(new B({5}))
or, less preferred and somewhat questionable, explicitly specify the template parameter:
make_unique<B, A>({5});
A constructor with a single non-default parameter (until C++11) that is declared without the function specifier explicit is called a converting constructor. Your A and B are instances of such constructors (this explains, why your first call works fine.) The problem is, that std::make_unique impedes these explicit calls. Anyhow, it might be a good idea, to not trust in these automatic creation in the first place and spent a few chars to show types. This could improve the readability of the code.

C++11 value initializer vs list initializer

It seems empirically that C++ always prefers a list initializer over a value initializer. My question is thus how can I force value initialization of a type that also supports a direct list initialization. Here is a minimal non-working example:
#include <initializer_list>
using namespace std;
struct foo {
foo(int) {}
foo(initializer_list<char>) {}
};
struct bar {
foo f{256};
};
In this example, I would like f to be initialized using the constructor foo(int) rather than the foo(initializer_list<char>). However, both GCC and Clang reject the code because 256 is too big for a char, which means the C++ spec requires choosing the list initializer. Obviously commenting out the second constructor of foo fixes the problem. What's the easiest way to define bar so as to use value initialization on field f? Ideally I could avoid copy initializing f, because in my real example there is no copy constructor.
update
To clarify: of course it's possible to initialize f explicitly in every single constructor of bar. But my question is specifically about the member initialization syntax because in situations with huge numbers of constructors it is preferable just to initialize certain fields in one place rather than to copy the code all over.
So long as you require foo to be non copyable/moveable, and you require foo to have an initializer_list constructor that could be used instead of a constructor, this is the behavior you get. Therefore, you have to change one of these facts if you want to solve this problem.
If you cannot change the definition of foo at all, then you're screwed. Complain to whomever owns the class.
The second fact is probably the easiest to change, but even that will not be without consequences:
struct il {};
struct foo {
foo(int) {}
foo(il, initializer_list<char>) {}
};
This completely disambiguate the problem. foo{256} will always call the single-integer constructor. However, foo technically has no initializer_list constructors; you instead must use the tag type il to call it with an initializer list of values:
foo f{il{}, {/*actual list*/}};
This requires more braced, but there is no real alternative.
Note that in C++17, guaranteed elision lets you do this:
struct bar {
foo f = foo(256);
};
Regardless of whether foo is mobile or not.

Template member default initialization

Suppose I have got the following template
template <typename T>
class{
T t;
};
Now, I want to add a constructor that initializes t with the default value for its type. That is, for numerical types, t should be initialized with 0, for pointers, t should be initialized with nullptr. Finally, there could be other types like structs. Here, a good initialization would be the default constructor (which is invoked anyway, so I do not have to do anything here).
In conlusion I am looking for something like this:
template<typename T>
class X{
T t;
X() : t(default_value<T>::value);
}
As my imaginary syntax points out, I think it could be possible with some kind of template with different specializations which carry the default values. But how to handles structs and classes? Since I have specified t(...), the default constructor is no longer an option.
You can just do
X() : t() { }
And/or this in C++11
X() : t { } { } // see Johannes Schaub's comments about this
That will value initialise (or is it default initialisation?) t to whatever the default value is for its type, be it 0 for built-in's, a series of (value?default) initialisations for arrays, or using the default constructor for user-defined types.

c++ why is constructor in this example called twice?

I just try to understand the behaviour of the following situation:
template <typename T1>
struct A{
template <typename T2>
A(T2 val){
cout<<"sizeof(T1): "<<sizeof(T1)<<" sizeof(T2): "<<sizeof(T2)<<endl;
}
T1 dummyField;
};
so - the class is templated with T1 and the constructor is templated with T2
now - if i write:
A<bool> a = A<bool>(true);
the output is as expected:
sizeof(T1): 1 sizeof(T2): 1
however - if i write:
A<bool> a = A<float>(3.5f);
the output is:
sizeof(T1): 4 sizeof(T2): 4
sizeof(T1): 1 sizeof(T2): 4
why is the constructor called twice with template parameter float?
thanks for satisfying my curiosity
How to avoid copying?
In both cases two constructors are called, however you do not see it in the first case as one of them is the compiler generated one. If you want to avoid copying, you need to use a different syntax, like this:
A<bool> a(true);
A<bool> a(3.5f);
Why (and what) copy constructor is called?
A<bool> a = A<bool>(true);
Here the A (bool val) constructor is used to construct the temporary value, while default compiler generated copy constructor is used to perform the copy of A to A. You are copying the same type, and for same type copy constructor is used. The interesting and not obvious fact here is: Template constructor is never used as a copy constructor, even if it looks like one.
A<bool> a = A<float>(3.5f);
Here A<float>(float val) constructor is used first to construct the temporary value, and then A<bool>( A<float> val) templated constructor is used to perform the copy.
in your first example you make a implicit call to the copy constructor
A<bool>(A<bool> const&)
in your second example this wont work as you have two different types
so the compiler has to use your templated constructor to create a new object
declaring
template <typename T2>
A(A<T2>const& val){
cout<<sizeof(val.dummmyField)<<endl;
}
should make this clear
Because you first create a float-instance of the template class.
This is the A<float>(3.5f)-Part.
Then create the A<bool> by covert the A<float> to a A<bool>. So the constructor is first called for the A<float>-instance. The the copy-constructor of A<bool> is called.