c++return-typeauto

How to specify an inferred (auto) return type in an `if constexpr` branch that always throws?


How can I specify the return type of a function with an inferred (auto) return type, when the body contains multiple if constexpr branches and one of them unconditionally throws?

The return type must satisfy a certain concept; I cannot just leave it as void.

I tried using std::declval but g++ static assert me with "you cannot use declval".

The question is, is there any better approach to declare a return type except than a fake return?

auto func()
{
   if constexpr (A)
   {
      if (...) return std::vector<int>{}; // actually something difficult to initialize
   }
   if constexpr (A && C)
   {
      throw 5;
      // fake return to declare return type - same type as if constexpr (A) above
      // return std::move(std::declval<std::vector<int>>()); // static assert in std library
      return std::move(*static_cast<std::vector<int>*>(nullptr)); // it works! is there any better way?
   }
   else return std::array<double, 5>{}; 
}

Solution

  • While I would argue the premise is wonky, you can create a kludge for it with the help of an immediately invoked lambda.

    return []() -> std::vector<int> { throw 5; }();
    

    The lambda is valid (though arcane), since its body never actually flows of the end to cause undefined behavior. And the explicit return type gives the whole expression the type we wish to deduce from in the return statement.

    You can also spin this into a helper template, as suggested in the comments to your question.