Please refer to the following C++20 code:
template<bool op>
class Person
{
const bool own_pet;
public:
Person() : own_pet(op) {}
consteval bool OwnPet() const { return own_pet; }
consteval bool OwnPetC() const { return true; }
void PatPet() const {}
};
template<typename T>
concept MustOwnPet = requires(T obj) {
requires obj.OwnPet();
};
void pat(const MustOwnPet auto& p)
{
p.PatPet();
}
template<typename T>
concept MustOwnPetC = requires(T obj) {
requires obj.OwnPetC();
};
void pat_c(const MustOwnPetC auto& p)
{
p.PatPet();
}
int main()
{
// Error in gc 12.1 with -std=c++20:
// in 'constexpr' expansion of 'obj.Person<true>::OwnPet()'
// <source>:16:24: error: 'obj' is not a constant expression
// Also doesn't compile in clang 14.0.0 with -std=c++20
// pat(Person<true>());
// Error in clang 14.0.0 with -std=c++20
// Compiles fine in gcc 12.1 with -std=c++20
pat_c(Person<true>());
return 0;
}
My understanding is that both Person::OwnPet()
and Person::OwnPetC()
are compile time functions as op
is known as compile time as instantiated in main()
.
Then why the pat()
fails to compile? Please see error in the code comment.
And pat_c()
fails to compile only in clang
but compiles fine in gcc
. Which compiler is correct?
The problem is that the parameter named obj
is not a constant expression. Thus it cannot be used in an evaluated context where a constant expression is required. For example, we cannot use obj
as a template nontype parameter(TNP) as TNP must be compile time constant which obj
is not.
Which compiler is correct?
This seems to be a bug in gcc submitted here