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...
CodePudding user response:
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.data())>(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;
}
CodePudding user response:
Just have one return.
auto test() {
return e.empty() ? nullptr : &e[0];
}
you should explain the issue with OPs code
There are two returns with different type. Which type to choose?
and why this fixes it – 463035818_is_not_a_number
Because there are super long rules what type is the result of conditional operator. See https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator