Sometimes we write a function without any intention of it ever being
invoked.
I do this often, but in all cases where I've done this it can be consteval, and it's with an auto or decltype(auto) return type.
Consider the following function to get a function's return
type:
template <typename ReturnType, typename... Params>
ReturnType ToReturnType( ReturnType (*)(Params...) )
{
// empty function body
}
If the function body is empty then it can typically be a variable template or an alias template. Or have no function body at all. You don't need to define it if you're not calling it.
The only reason we write a function like this is to use 'decltype' on
its invocation, some thing like:
typedef decltype( ToReturnType(my_function_pointer) ) ReturnType;
Most compilers will warn that the above function doesn't have a return
statement, so I suppress the warning with:
template <typename ReturnType, typename... Params>
ReturnType ToReturnType( ReturnType (*)(Params...) )
{
return std::declval<ReturnType>();
}
Which doesn't work if the type is not movable.
You can use std::unreachable(), that's what it's for. It just don't define the function body.
It though it might be more intuitive though to mark the function:
template <typename ReturnType, typename... Params>
[[unevaluated]] ReturnType ToReturnType( ReturnType (*)(Params...) ) {}
It's more intuitive to just not define it if you don't want to be able to call it.
We don't need new language features to do this.
This would have two effects:
(1) The compiler will refuse to use it in an evaluated context
(2) The compiler won't give a warning/error about a missing return statement