在 consteval 成员函数中使用“int”成员作为模板参数

问题描述 投票:0回答:1

我正在尝试使用

int
对象的
constexpr
成员作为模板参数。我的想法是,我创建一个
constexpr Symbol
,然后将其转换为
SymbolRef<1>
(在实际代码中,1 对于不同的对象是不同的)。

template<int Id>
struct SymbolRef { };

struct Symbol {
  int const id_;

  consteval Symbol() : id_(1) { }

  template<int Id>
  consteval operator SymbolRef<Id>() const
  {
    return SymbolRef<id_>{};
  }
};

但是,尝试编译上述代码时出现错误:

error: non-type template argument is not a constant expression
   12 |     return SymbolRef<id_>{};
      |                      ^~~
<source>:12:22: note: implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function

短语“仅允许在调用‘constexpr’成员函数的评估中使用”似乎不适用:这一个

consteval
函数!?

我知道,当

operator SymbolRef<Id>()
constexpr
成员函数时(尽管有错误消息!),此代码格式不正确,因为在这种情况下,该函数还必须在没有
constexpr
的情况下进行编译,在这种情况下
 this->id_
不能用作模板参数。

为什么这段代码与

consteval
一起使用时是非法的?

编辑:

以下确实使用g++进行编译 - 但仅在使用

this->id_
时。

template<int Id>
struct SymbolRef { };

struct Symbol {
  int const id_;

  consteval Symbol() : id_(1) { }

  template<int Id>
  consteval operator SymbolRef<Id>() const
  {
    return SymbolRef<this->id_>{};
  }
};

我猜这是一个编译器错误?看来正确的行为是无论有没有

this->
都可以编译,而 clang++ 是错误的。

c++ compiler-errors c++20
1个回答
0
投票

consteval
/
constexpr
与此处无关。

非类型模板参数,无论出现在何处,其本身都必须是常量表达式。

您引用的规则是不完整的。 [expr.const]/5.1 说:

表达式 E 是核心常量表达式,除非对 E 的求值遵循抽象机 ([intro.execution]) 的规则,将求值以下其中一项:

  • [...]
  • this
    ,除了作为 E 的一部分进行计算的 constexpr 函数;
  • [...]
模板参数中的

id_
隐式解释为
this->id_
,因为
id_
命名了类的成员。这个
this
确实出现在 constexpr 函数内部,但不是在考虑的常量表达式求值期间调用的 constexpr 函数。

要了解为什么这不起作用,请考虑编译器必须在实例化模板时确定每个表达式的类型,然后才能知道可能调用函数的

id_
的值。每次调用相同的函数特化时,类型是否应该不同?这在静态类型语言中是不可能的。

© www.soinside.com 2019 - 2024. All rights reserved.