Vit*_*meo 19 c++ sfinae language-lawyer c++17 if-constexpr
考虑两个struct具有不同成员类型别名的s:
struct foo { using x = int; };
struct bar { using y = float; };
Run Code Online (Sandbox Code Playgroud)
给定T的template情况下,我想无论是T::x还是T::y取决于什么T是:
template <typename T>
auto s()
{
auto l = [](auto p)
{
if constexpr(p) { return typename T::x{}; }
else { return typename T::y{}; }
};
return l(std::is_same<T, foo>{});
}
int main()
{
s<foo>();
}
Run Code Online (Sandbox Code Playgroud)
g++编译上面的代码,同时clang++产生这个错误:
error: no type named 'y' in 'foo'
else { return typename T::y{}; }
~~~~~~~~~~~~^
note: in instantiation of function template specialization 's<foo>' requested here
s<foo>();
^
Run Code Online (Sandbox Code Playgroud)
被clang++不正确地拒绝这个代码?
注意,clang++通过通用lambda删除间接时接受代码l:
template <typename T>
auto s()
{
if constexpr(std::is_same<T, foo>{}) { return typename T::x{}; }
else { return typename T::y{}; }
}
Run Code Online (Sandbox Code Playgroud)
请参阅Richard Smith关于std讨论的帖子:
在我熟悉[即Clang]的实现中,一个关键问题是在处理函数定义时使用的词法范围基本上是暂时的,这意味着延迟函数模板定义的某些部分的实例化很难支持.通用lambda不会遇到问题,因为泛型lambda的主体用封闭的函数模板实例化,[...]
也就是说,在实例化模板时,使用本地上下文(包括模板参数)部分地实例化通用lambdas的实体; 从而下铛的实现,T::x并且T::y被直接取代的,因为封闭件类型可以外面通过.这导致了失败.正如@TC所指出的,代码可以被认为是不正确的,不需要诊断,因为实例化s<foo>产生模板定义(闭包的模板定义),其第二个if constexpr分支没有良好形成的实例化.这解释了Clang和GCC的行为.
这归结为一个主要实现中的架构问题(另见这个答案 ; GCC显然没有受到这个限制),所以如果Core认为你的代码格式正确(毕竟,他们占了这在通用lambda捕获的设计中 - 参见链接的答案).支持代码的GCC充其量只是一个功能(但可能有害,因为它使您能够编写依赖于实现的代码).
| 归档时间: |
|
| 查看次数: |
363 次 |
| 最近记录: |