为什么成员函数 return 类型的实例化要比它所依赖的表达式类型晚得多?
Why is member function return type instantiated much later than the expression types it depends on?
请原谅这个令人困惑的标题。
我有这段代码,它被 GCC、Clang 和 MSVC 接受:
#include <type_traits>
template <typename T>
struct Reader
{
friend auto adl(Reader<T>);
};
template <typename T, typename U>
struct Writer
{
friend auto adl(Reader<T>) {return U{};}
};
struct A
{
struct Tag {};
auto helper() -> decltype(void(Writer<Tag,decltype(this)>{})) {}
using Self = std::remove_pointer_t<decltype(adl(Reader<Tag>{}))>;
};
它使用有状态元编程来编写一个类型,然后再读回它。
注意 Writer
的奇怪用法。我想我可以将其简化为:
auto helper() -> Writer<Tag,decltype(this)> {return {};}
但随后它停止工作(在所有三个编译器上),因为 Writer
在读取发生后被实例化。 run on gcc.godbolt.org
但是,如果我随后将 using Self = ...
移动到 helper
下面的 static
函数 body,它将再次开始工作。意思是 Writer
现在与 helper
的 body 一起实例化,而不是与其声明一起实例化。
在尝试了不同的 return 类型之后,似乎 Writer
在用作 表达式 的类型时会提前实例化。这是另一个例子:auto helper() -> std::enable_if_t<(Writer<Tag,decltype(this)>{}, true), void> {}
造成这种差异的原因是什么?既然三个编译器都同意这一点,这不是有状态模板的侥幸,对吧?
声明 auto helper() -> Writer<Tag,decltype(this)>;
不会导致 Writer<Tag,decltype(this)>
的实例化,因为 return 类型不需要完整。
helper()
的定义以及 Writer<Tag,decltype(this)>
的隐式实例化然后在 complete-class 上下文中,编译器似乎认为这意味着成员函数定义位于在 class 定义之后,并且 Writer<Tag,decltype(this)>
的 point-of-instantiation 也在 class 定义之后。
不过,我不知道这是否真的应该如何工作,或者标准中的哪一段会指定此行为。
仅在另一个(静态)成员函数的主体中读取标记会导致读取也位于完整的 class 上下文中,即在上述解释中的 class 定义之后,这就是它再次起作用的原因。
请原谅这个令人困惑的标题。
我有这段代码,它被 GCC、Clang 和 MSVC 接受:
#include <type_traits>
template <typename T>
struct Reader
{
friend auto adl(Reader<T>);
};
template <typename T, typename U>
struct Writer
{
friend auto adl(Reader<T>) {return U{};}
};
struct A
{
struct Tag {};
auto helper() -> decltype(void(Writer<Tag,decltype(this)>{})) {}
using Self = std::remove_pointer_t<decltype(adl(Reader<Tag>{}))>;
};
它使用有状态元编程来编写一个类型,然后再读回它。
注意 Writer
的奇怪用法。我想我可以将其简化为:
auto helper() -> Writer<Tag,decltype(this)> {return {};}
但随后它停止工作(在所有三个编译器上),因为 Writer
在读取发生后被实例化。 run on gcc.godbolt.org
但是,如果我随后将 using Self = ...
移动到 helper
下面的 static
函数 body,它将再次开始工作。意思是 Writer
现在与 helper
的 body 一起实例化,而不是与其声明一起实例化。
在尝试了不同的 return 类型之后,似乎 Writer
在用作 表达式 的类型时会提前实例化。这是另一个例子:auto helper() -> std::enable_if_t<(Writer<Tag,decltype(this)>{}, true), void> {}
造成这种差异的原因是什么?既然三个编译器都同意这一点,这不是有状态模板的侥幸,对吧?
声明 auto helper() -> Writer<Tag,decltype(this)>;
不会导致 Writer<Tag,decltype(this)>
的实例化,因为 return 类型不需要完整。
helper()
的定义以及 Writer<Tag,decltype(this)>
的隐式实例化然后在 complete-class 上下文中,编译器似乎认为这意味着成员函数定义位于在 class 定义之后,并且 Writer<Tag,decltype(this)>
的 point-of-instantiation 也在 class 定义之后。
不过,我不知道这是否真的应该如何工作,或者标准中的哪一段会指定此行为。
仅在另一个(静态)成员函数的主体中读取标记会导致读取也位于完整的 class 上下文中,即在上述解释中的 class 定义之后,这就是它再次起作用的原因。