Automatic Object Construction in Function Parameters by Passing Constructor Parameters - c++

Can you explain why the following code compiles and runs? What is the concept at play here, and what are the limitations/requirements for such a methodology to work?
class string_wrapper
{
public:
string_wrapper(string i_string);
string m_value;
int m_length;
};
string_wrapper::string_wrapper(string i_string)
{
m_value = i_string;
m_length = i_string.length();
}
void bar(string_wrapper i_param)
{
cout << i_param.m_value << std::endl;
}
void foo()
{
string test_string = "test1";
bar(test_string);
}
int main()
{
test_function_b();
}
Output:
test1
I would expect this code to not compile. foo() is passing a string parameter to bar(), when bar only takes a string_wrapper parameter. However, the compiler is smart enough to know that it can use the string parameter as a parameter to a constructor for a string_parameter object, which presumably is then passed on as the actual parameter to bar().
Is this behavior within the C++ standard, or unique to my compiler (Visual Studio 2017, version 15.9, in this case)? Any insight or terminology I can use for further research would be appreciated.

Whats going on here is implicit construction. You are right about the compiler being 'smart' enough to know that you can create a string_wrapper out of a std::string and so does it automatically for you.
To stop this happening you can use the explcit keyword like this:
...
explicit string_wrapper(string i_string);
...
The explicit keyword tells the compiler that you do not want it to automatically construct string_wrapper objects for you out of std::string's. This can stop hard to track down bugs because it prevents accidentally constructing objects (especially on function returns and when passing arguments).
Implicit construction can happen when an object has only one non-defaulted parameter (implicit conversion is something you should research as well). It can be a powerful tool and can allow things like proxy classes and transparent APIs (i.e std::vector's reference class). Generally you should declare single parameter (or single undefaulted value) constructors (and conversion operators) explicit unless you are making a design decision not too.

Related

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.

Is it possible to know if the parameter was defaulted

Caution: This problem is limited to MSVS
I have this function signature:
void do_somthing(std::vector<foo>& bar={});
Is it possible to differ between those two calls for the function:
First:
do_something()
Second:
std::vector<foo> v;
do_something(v);
In other words, I want something like:
void do_somthing(std::vector<foo>& bar={}){
if(/* bar was defaulted*/){
}
else{
}
}
EDIT:
The actual code:
template<class Tinput_iterator>
Tmodel perform_fitting(Tinput_iterator begin_data, Tinput_iterator end_data, std::vector<Tpoint>& inliers = {});
No, not directly. The default parameter is substituted by the compiler at the call site without any further information.
However, there is a simple solution to achieve what you want to do: Use overloading instead of default parameters.
namespace detail
{
void
do_something_impl(const std::vector<foo>& foos)
{
// Do things that always need to be done…
}
}
void
do_something()
{
// Do things specific to the no-argument case…
detail::do_something_impl({});
}
void
do_something(const std::vector<foo>& foos)
{
// Do things specific to the one-argument case…
detail::do_something_impl(foos);
}
If your logic requires you to branch more often – not just at the beginning or the end of the function – you could pass an additional boolean parameter to detail::do_something_impl that encodes which overload it was called from.
In general, I recommend to use defaulted parameters sparingly and prefer function overloading as it gives you better control and often also better (less surprising) interfaces.
I have this function signature:
void do_somthing(std::vector<foo>& bar=std::vector<foo>{});
This cannot compile, except with dangerous non-standard compiler settings you should stay away from.
In particular, Visual C++ allows this if /Za is not specified, but with /W4 still produces a warning like this:
stackoverflow.cpp(6): warning C4239: nonstandard extension used: 'default argument': conversion from 'std::vector<foo,std::allocator<_Ty>>' to 'std::vector<foo,
std::allocator<_Ty>> &'
with
[
_Ty=foo
]
stackoverflow.cpp(6): note: A non-const reference may only be bound to an lvalue
void do_somthing(std::vector<foo>& bar=std::vector<foo>{}){
if(/* bar was defaulted*/){
}
else{
}
}
Even if we assume that you actually included the missing const to make the code compile, the answer would be: no, it is not possible to know if bar was defaulted.
Whatever you plan to do here, you have to find a completely different solution.
Is it possible to differ between those two calls for the function?
No. You can check if the vector is empty, but otherwise there is no way to distinguish them.
You can do clever things, such as passing a utility class that converts, but that isn't bulletproof and is mostly pointless since you can more easily make two different function overloads.

Reference qualifiers and deleted member methods

Consider the following code:
#include<utility>
struct S {
void f(int) = delete;
void f(int) && { }
};
int main() { }
It doesn't compile saying that the member method cannot be overloaded and it makes sense, of course.
On the other side, the following code compiles:
#include<utility>
struct S {
void f(int) & = delete;
void f(int) && { }
};
int main() {
S s;
// s.f(42); <-- error, deleted member method
std::move(s).f(42);
}
Is that legal code?
Wouldn't it be possible to define two completely different interfaces within the same class, the former to be used with lvalues, the latter with rvalues?
Apart from the fact that it doesn't make much sense, but it really hurts me.
Shouldn't a deleted function be deleted as a whole, instead of deleted only if you are a lvalue?
Which is the purpose of this feature? Is it the classic obscure corner case or is there something more I can't see?
Sometimes it makes sense to prohibit certain operations if object is l- or r-value.
Imagine RAII wrapper for FILE*. It opens file in constructor, closes it in destructor, turning C feature requiring manual control to C++ exception-safe class. To interact with C interface, there is a .get() member which returns raw pointer. Someone might write:
FILE* file = CFile("file.txt").get();
It would compile, but it is wrong: file would be closed as soon, as file variable would be initialized. If you delete an r-value overload (on never provide it in the first place), then it would lead to compile-time error and save us from bug-hunting.

Object construction/Forward function declaration ambiguity

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.
Hello,
It wasn't for just a few times that I stumbled into an object construction statement that I didn't understand, and it was only today that I noticed what ambiguity was being introduced by it. I'll explain how to reproduce it and would like to know if there's a way to fix it (C++0x allowed). Here it goes.
Suppose there is a class whose constructor takes only one argument, and this one argument's type is another class with a default constructor. E.g.:
struct ArgType {};
class Class
{
public:
Class(ArgType arg);
};
If I try to construct an object of type Class on the stack, I get an ambiguity:
Class c(ArgType()); // is this an object construction or a forward declaration
// of a function "c" returning `Class` and taking a pointer
// to a function returning `ArgType` and taking no arguments
// as argument? (oh yeh, loli haets awkward syntax in teh
// saucecode)
I say it's an object construction, but the compiler insists it's a forward declaration inside the function body. For you who still doesn't get it, here is a fully working example:
#include <iostream>
struct ArgType {};
struct Class {};
ArgType func()
{
std::cout << "func()\n";
return ArgType();
}
int main()
{
Class c(ArgType());
c(func); // prints "func()\n"
}
Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works
{
funcPtr();
return Class();
}
So well, enough examples. Anyone can help me get around this without making anything too anti-idiomatic (I'm a library developer, and people like idiomatic libraries)?
-- edit
Never mind. This is a dupe of Most vexing parse: why doesn't A a(()); work?.
Thanks, sbi.
This is known as "C++'s most vexing parse". See here and here.
Let's simplify a little.
int f1();
What's that? The compiler (and I) say it's a forward declaration for a function returning an integer.
How about this?
int f2(double );
The compiler (and I) say it's a forward declaration for a function taking a double argument and returning an int.
So have you tried this:
ClassType c = ClassType(ArgType());
Check out the c++ faq lite on constructors for explanations and examples
Based on the "C++0x allowed", the right answer is (probably) to change the definition to:
Class c(ArgType {});
Simple, straightforward and puts the burden entirely on the user of the library, not the author!
Edit: Yes, the ctor is invoked -- C++ 0x adds List-Initialization as an unambiguous way to delimit initializer lists. It can't be mis-parsed like in your sample, but otherwise the meaning is roughly the same as if you used parentheses. See N3000, the third bullet point under §8.5.4/3. You can write a ctor to receive an initializer list as a single argument, or the items in the initializer list can be matched up with the ctor arguments individually.

Default parameters with C++ constructors [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Is it good practice to have a class constructor that uses default parameters, or should I use separate overloaded constructors? For example:
// Use this...
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo(const std::string& name = "", const unsigned int age = 0) :
name_(name),
age_(age)
{
...
}
};
// Or this?
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo() :
name_(""),
age_(0)
{
}
foo(const std::string& name, const unsigned int age) :
name_(name),
age_(age)
{
...
}
};
Either version seems to work, e.g.:
foo f1;
foo f2("Name", 30);
Which style do you prefer or recommend and why?
Definitely a matter of style. I prefer constructors with default parameters, so long as the parameters make sense. Classes in the standard use them as well, which speaks in their favor.
One thing to watch out for is if you have defaults for all but one parameter, your class can be implicitly converted from that parameter type. Check out this thread for more info.
I'd go with the default arguments, especially since C++ doesn't let you chain constructors (so you end up having to duplicate the initialiser list, and possibly more, for each overload).
That said, there are some gotchas with default arguments, including the fact that constants may be inlined (and thereby become part of your class' binary interface). Another to watch out for is that adding default arguments can turn an explicit multi-argument constructor into an implicit one-argument constructor:
class Vehicle {
public:
Vehicle(int wheels, std::string name = "Mini");
};
Vehicle x = 5; // this compiles just fine... did you really want it to?
This discussion apply both to constructors, but also methods and functions.
Using default parameters?
The good thing is that you won't need to overload constructors/methods/functions for each case:
// Header
void doSomething(int i = 25) ;
// Source
void doSomething(int i)
{
// Do something with i
}
The bad thing is that you must declare your default in the header, so you have an hidden dependancy: Like when you change the code of an inlined function, if you change the default value in your header, you'll need to recompile all sources using this header to be sure they will use the new default.
If you don't, the sources will still use the old default value.
using overloaded constructors/methods/functions?
The good thing is that if your functions are not inlined, you then control the default value in the source by choosing how one function will behave. For example:
// Header
void doSomething() ;
void doSomething(int i) ;
// Source
void doSomething()
{
doSomething(25) ;
}
void doSomething(int i)
{
// Do something with i
}
The problem is that you have to maintain multiple constructors/methods/functions, and their forwardings.
In my experience, default parameters seem cool at the time and make my laziness factor happy, but then down the road I'm using the class and I am surprised when the default kicks in. So I don't really think it's a good idea; better to have a className::className() and then a className::init(arglist). Just for that maintainability edge.
Sam's answer gives the reason that default arguments are preferable for constructors rather than overloading. I just want to add that C++-0x will allow delegation from one constructor to another, thereby removing the need for defaults.
Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.
class Thingy2
{
public:
enum Color{red,gree,blue};
Thingy2();
Thingy2 & color(Color);
Color color()const;
Thingy2 & length(double);
double length()const;
Thingy2 & width(double);
double width()const;
Thingy2 & height(double);
double height()const;
Thingy2 & rotationX(double);
double rotationX()const;
Thingy2 & rotatationY(double);
double rotatationY()const;
Thingy2 & rotationZ(double);
double rotationZ()const;
}
main()
{
// gets default rotations
Thingy2 * foo=new Thingy2().color(ret)
.length(1).width(4).height(9)
// gets default color and sizes
Thingy2 * bar=new Thingy2()
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
// everything specified.
Thingy2 * thing=new Thingy2().color(ret)
.length(1).width(4).height(9)
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}
Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)
Also, you no longer have to remember the order of the arguments to the constructor.
One more thing to consider is whether or not the class could be used in an array:
foo bar[400];
In this scenario, there is no advantage to using the default parameter.
This would certainly NOT work:
foo bar("david", 34)[400]; // NOPE
Mostly personal choice. However, overload can do anything default parameter can do, but not vice versa.
Example:
You can use overload to write A(int x, foo& a) and A(int x), but you cannot use default parameter to write A(int x, foo& = null).
The general rule is to use whatever makes sense and makes the code more readable.
If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.
Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.
The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.
Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.
I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.
One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.
In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.
Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.
I personally like defaults when appropriate, because I dislike repeated code. YMMV.