c++lambdalanguage-lawyerc++20c++-concepts

How can I disable concept evaluation result caching?


It appears that all compilers perform caching of concepts' evaluations. So if some concept was evaluated as false once, it will not be reevaluated again for the same argument:

template <typename T>
concept C = T::a;

struct A;
static_assert(!C<A>);

struct A { static constexpr bool a = true; };
static_assert(C<A>); //< fails everywhere unless above static_assert is removed

Can I somehow deactivate this caching? I tried to add an additional template argument to the concept with a default value of lambda auto = []{}, which shall have a new type every time:

template <typename T, auto = []{}>
concept C = T::a;

struct A;
static_assert(!C<A>);

struct A { static constexpr bool a = true; };
static_assert(C<A>); //< fails in GCC only

It actually worked with Clang, EDG and MSVC. But GCC still performs caching from the previous concept evaluation C<A>, where it was false. Online demo: https://gcc.godbolt.org/z/fG1nx884x

Is GCC's behavior correct here?


Solution

  • You can't. This is [temp.constr.atomic]/3:

    If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required.

    That came from P2104. This rule permits concept evaluation caching, which significantly speeds up compilation time. You can't just turn it off.