There is this nice feature in C++ where you can say the function has return type "auto" and compiler will figure it out. However, what if I return a pointer and nullptr on error? Somehow compiler then fails to deduce the correct type and gives an error.
In the following simple example imagine std::vector<int>
is scheduled to be replaced by something else completely in future, to justify the use of auto here:
#include<vector>
std::vector<int> e;
auto test(){
if(!e.empty())
return &e[0];
return nullptr;
}
In c++17 I get above error message.
So I tried replacing last return by
return reinterpret_cast<decltype(&e[0])>(nullptr)
and get the error invalid cast
. Only solution I see is replacing that return by the 3 lines:
auto out=&e[0];
out=nullptr;
return out;
I probably could reduce that to 2 lines by replacing auto
with some kind of decltype
, but I imagine some other kind of cast could do what I want in a single line?
Or do I need to use a newer version of the c++ standard for that case?
I also tried std::make_optional and get the same problem with nullopt_t being different type than std::optional.
What I really would love is if compiler would automatically deduce type to be std::optional
anyway...
right, nullptr
is type std::nullptr_t
which is not type int*
.
Static cast should be ok.
#include<vector>
std::vector<int> e;
auto test(){
if(!e.empty())
return &e[0];
return static_cast<decltype(&e[0])>(nullptr);
}
https://godbolt.org/z/sqfnqd69q
Even if reinterpret_cast
worked (it doesn't), it would be overkill.
Regarding your follow up question, not sure what you want to achieve, but this seems close:
#include<vector>
#include<optional>
std::vector<int> e;
auto test(){
// if(!e.empty())
// return std::make_optional(e[0]);
// return decltype(std::make_optional(e[0]))(std::nullopt);
return e.empty()?std::nullopt:std::optional{e[0]};
}
I think this is more idiomatic:
#include<vector>
std::vector<int> e;
auto test(){
if(!e.empty())
return e.data();
return static_cast<std::vector<int>::pointer>(nullptr);
}
I am a fan of auto
, but this is one of the cases is better not to use it:
#include<vector>
std::vector<int> e;
auto test() -> std::vector<int>::pointer // int*
{
if(!e.empty())
return e.data();
return nullptr;
}