During my adventures with project I realised that I can't use the advantage of the new c++11 auto keyword if I want to initialise the parameter depending on the condition.
Basically I had a code snippet like this:
auto foo = bar::getfoo();
Which needed to be change to:
FOO foo
if(cond){
foo = bar::getfoo();
} else {
foo = baz::getotherfoo();
}
But then I need to declare the foo with the type (as the compiler can't know that I will be using the same type return. I was wondering if there is any way of using the auto keyword in such case. The other solution which I came up with is using the ? : operator with such code:
auto foo = cond ? bar::getfoo() : baz::getotherfoo();
But if there is more then two functions to choose from I don't really want to chain the ? : operators. I am wondering if there is any good pattern to use in such case.
Your instincts to use the ? : operator are correct - it's a good idea to initialise a variable only once and avoid the redundant default construction/assignment cycle.
A way to do this is to defer the selection of the Foo creation to a small utility function:
auto make_foo() -> decltype(bar::getfoo())
{
if (condition1()) {
return bar::getfoo();
}
else if(condition2()) {
return baz::getfoo();
}
else {
return banana::getfoo();
}
}
void foo_test() {
auto foo = make_foo();
}
Note that because of Return Value Optimisation, this is extremely efficient.
If you have c++14 it's even nicer - the make_foo() function can deduce its own return type:
auto make_foo() {
if (condition1()) {
return bar::getfoo();
}
else if(condition2()) {
return baz::getfoo();
}
else {
return banana::getfoo();
}
}
This is what decltype
is for. It will provide you with the type of an expression, without actually evaluating (and you could implement auto in terms off):
decltype(bar::getfoo()) foo;
if (....) {foo = ...;} else {foo = ...;}
auto a = foo();
constructs a
from foo()
;
std::decay<decltype( foo() )>::type a;
if(cond){
a = foo();
}else{
a = bar();
}
default constructs a
then assigns to it the result of foo()
or bar()
based on cond
.
decay
is needed as otherwise of foo()
returns a reference or a const decltype
will deduce the 'wrong' type for a
.
auto a = [&]{
if (cond)
return foo();
else
return bar();
}();
uses a C++14 feature (that most C++11 compilers supported early on), but conditionally calls either foo
or bar
and constructs a
from it. This logicalky requires an extra move, but the compiler will almost certainly elide it so it won't actually happen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With