当模板类对象用value实例化时, c++ 20概念编译失败



请参考以下c++ 20代码:

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;
}

我的理解是Person::OwnPet()Person::OwnPetC()都是编译时函数,因为opmain()实例化的编译时函数。

为什么pat()不能编译?请查看代码注释中的错误。

pat_c()只在clang中编译失败,在gcc中编译正常。哪个编译器是正确的?

问题是那个叫obj参数不是一个常数表达式。因此,它不能在需要常量表达式的求值上下文中使用。例如,我们不能使用obj作为模板非类型形参(TNP),因为TNP必须是编译时常数,而obj不是。

哪个编译器是正确的?

这似乎是在这里提交的gcc中的一个错误

以下代码适用于GCC 12.1-std=c++20。我不熟悉你想要实现的,但我想这里的问题是成员变量,这是相同的所有模板实例,因此应该是一个static constexpr。如果是这种情况,OwnPet()可以在编译时求值。在另一种情况下,对于我们人类来说,它也可以在编译时计算,这是合乎逻辑的,但我想编译器不会(因为访问成员变量而不是const表达式)

template<bool op>
class Person
{
static constexpr bool own_pet = op;
public:
Person() {}
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()
{
pat(Person<true>());
pat_c(Person<true>());
return 0;
}

相关内容

  • 没有找到相关文章

最新更新