Date: Thu, 21 May 2026 07:00:48 +0000
>
> Thiago wrote:
>
> > In this particular case, I think there's an extremely
> > weak but non-zero motivation. There is one function
> > in the standard library that would use it:
> > std::declval. But the problem is already solved for
> > that one, so the solution is available for other
> > functions like it.
>
When we want to write a function just to use it in an unevaluated context,
we just declare it without defining it, for example:
SomeClass &&GetRvalRefSomeClass(void);
And then we can for example use it in a 'noexcept' specifier, such as:
void SomeOtherFunction(void) noexcept( noexcept( SomeOtherRoutine(
GetRvalRefSomeClass() ) ) {}
But sometimes how the return type is chosen is more elaborate than that,
and so we write 'auto' or 'decltype(auto)' for the return type and then
provide a body, perhaps something like:
decltype(auto) Func()
{
if constexpr ( is_hosted ) return GetHost();
else if constexpr ( mylicense > max_licenses ) return
GetRestrictedHost();
else return std::declval< MonitoredHost& >();
}
Jonathan is right that such a function can instead be written something
like:
std::conditional_t<
is_hosted,
decltype(GetHost()),
std::conditional_t<
(mylicense > max_licenses),
decltype(GetRestrictedHost()),
MonitoredHost&
>
>
And that's fine when it's not too complicated. But sometimes it's much more
complicated than that, especially if the type is dependent upon the
compile-time constant output from a consteval hash function (such as the
digest for a string from the MD5 algorithm). I'm not saying you can't do it
with 'conditional_t', but it just gets a bit hairy. A function can have
static_assert's inside it too though -- so that's another advantage over
'conditional_t'.
That's why I think we should tell the compiler the following: "This
function is not intended to be invoked -- not at compile time nor runtime.
Its only purpose is to be used in unevaluated contexts, so please don't
give warnings that would only be worrisome if the function were actually
invoked". And I think the best way to tell the compiler this is to write
[[unevaluated]] beside it.
> Thiago wrote:
>
> > In this particular case, I think there's an extremely
> > weak but non-zero motivation. There is one function
> > in the standard library that would use it:
> > std::declval. But the problem is already solved for
> > that one, so the solution is available for other
> > functions like it.
>
When we want to write a function just to use it in an unevaluated context,
we just declare it without defining it, for example:
SomeClass &&GetRvalRefSomeClass(void);
And then we can for example use it in a 'noexcept' specifier, such as:
void SomeOtherFunction(void) noexcept( noexcept( SomeOtherRoutine(
GetRvalRefSomeClass() ) ) {}
But sometimes how the return type is chosen is more elaborate than that,
and so we write 'auto' or 'decltype(auto)' for the return type and then
provide a body, perhaps something like:
decltype(auto) Func()
{
if constexpr ( is_hosted ) return GetHost();
else if constexpr ( mylicense > max_licenses ) return
GetRestrictedHost();
else return std::declval< MonitoredHost& >();
}
Jonathan is right that such a function can instead be written something
like:
std::conditional_t<
is_hosted,
decltype(GetHost()),
std::conditional_t<
(mylicense > max_licenses),
decltype(GetRestrictedHost()),
MonitoredHost&
>
>
And that's fine when it's not too complicated. But sometimes it's much more
complicated than that, especially if the type is dependent upon the
compile-time constant output from a consteval hash function (such as the
digest for a string from the MD5 algorithm). I'm not saying you can't do it
with 'conditional_t', but it just gets a bit hairy. A function can have
static_assert's inside it too though -- so that's another advantage over
'conditional_t'.
That's why I think we should tell the compiler the following: "This
function is not intended to be invoked -- not at compile time nor runtime.
Its only purpose is to be used in unevaluated contexts, so please don't
give warnings that would only be worrisome if the function were actually
invoked". And I think the best way to tell the compiler this is to write
[[unevaluated]] beside it.
Received on 2026-05-21 07:00:53
