C++ Logo

std-proposals

Advanced search

Re: [std-proposals] attribute [[unevaluated]]

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Thu, 22 May 2025 09:02:01 +0100
On Thu, 22 May 2025, 08:47 Frederick Virchanza Gotham via Std-Proposals, <
std-proposals_at_[hidden]> wrote:

> On Wed, May 21, 2025 at 12:54 AM Thiago Macieira wrote:
> >
> > decltype(std::declval<T (*)()>()())
>
>
> That's clever. But every modern C++ compiler fails to compile the
> following source file:
>
> #include <string> // string
> #include <utility> // declval
>
> template<typename T>
> decltype(auto) consteval Func(void) noexcept
> {
> return std::declval<T(*)(void)>()();
> }
>
> int main(void)
> {
> typedef decltype(Func<std::string>()) MyType;
> }
>
> The problematic line is the return statement from 'Func', as the
> compiler thinks that the result of 'declval' is being used in an
> evaluated context.
>
> The solution, I think, is to apply an attribute to 'Func' as follows:
>
> template<typename T>
> [[unevalutated]] decltype(auto) consteval Func(void) noexcept
> {
> return std::declval<T(*)(void)>()();
> }
>
> This attribute will have two effects:
> (1) It will disallow the compiler to call this function in an
> evaluated context
> (2) It will allow unrestricted use of "declval" inside the body of
> the function
>

You.

Don't.

Need.

It.

Firstly, for the example above, just return

static_cast<T(*)()>(nullptr)

You don't need declval here.

But that's just the wrong approach anyway.

You are trying to write a metafunction for working with types, so just do
that. Use the existing language features properly, instead of trying to add
unnecessary complexity.

You can write the expression you want in an unevaluated context today, now,
with existing compilers. Then turn that into a type that can encode the
result you want, and then extract that result when ready to use it.

template<typename T>
    consteval auto Func() noexcept
    {
        using result = T(*)();
        return type_identity<result>{};
    }

The 'result' type can be an arbitrary decltype(...) expression, which is an
unevaluated context so can use std::declval.

Received on 2025-05-22 08:02:17