Как я могу указать тип возвращаемого значения функции с выведенным (auto
) типом возвращаемого значения, если тело содержит несколько ветвей if constexpr
и одна из них безоговорочно выбрасывает?
Тип возвращаемого значения должен удовлетворять определенной концепции; Я не могу просто оставить это как void
.
Я пробовал использовать std::declval
, но статический g++ утверждает меня: «Вы не можете использовать declval».
Вопрос в том, есть ли лучший способ объявить возвращаемый тип, кроме ложного возврата?
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>{};
}
Принимает ли фактическая функция аргумент? Можно ли использовать шаблоны? Как насчет концепций C++20? Перегрузка? Специализация шаблона?
Я бы объявил помощника типа template <typename T> [[noreturn]] inline static T never() { std::unreachable(); }
, а затем просто return never<std::vector<int>>();
.`
@user3840170 user3840170 — встроенный или статический. В противном случае это просто многословный способ сказать static
. Это также отличный ответ в C++17, если вы используете std::exit
вместо std::unreachable
.
Примечание: вместо того, чтобы бросать, вы можете рассмотреть возможность возврата std::expected.
@Someprogrammerdude Фактическая функция принимает параметры и пакет параметров, это шаблонная функция в шаблонном классе, и я работаю с C++26. Функция может возвращать МНОГО разных типов, но все они удовлетворяют одной и той же концепции.
Хотя я бы сказал, что эта предпосылка шаткая, вы можете создать для нее кладж с помощью немедленно вызываемой лямбды.
return []() -> std::vector<int> { throw 5; }();
Лямбда действительна (хотя и загадочна), поскольку ее тело никогда не переходит в конец, вызывая неопределенное поведение. А явный возвращаемый тип придает всему выражению тот тип, который мы хотим получить в операторе return.
Вы также можете превратить это в вспомогательный шаблон, как предложено в комментариях к вашему вопросу.
Честно говоря, это немного проблематично. «Конкретную концепцию», которая не применима к пустоте, я бы лично попытался пересмотреть в первую очередь.