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?
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.