【发布时间】:2020-05-29 21:50:14
【问题描述】:
似乎 Clang (9.0.0) 有问题,或者我对如何指定 decltype() 在标准中工作的理解。参考以下代码,
#include <utility>
#include <string>
template <typename...> class WhichType;
template <typename T>
std::remove_reference_t<T>&& move_v2(T&& t) {
WhichType<std::remove_reference_t<T>&&>{};
return static_cast<std::remove_reference_t<T>&&>(t);
}
int main() {
auto x = std::string{"a"};
[v = x]() {
// move_v2(v);
// WhichType<decltype(move_v2(v))>{};
WhichType<decltype(std::move(v))>{};
}();
}
上面的代码在WhichType 的模板参数中具有编译器输出implicit instantiation of undefined template 'WhichType<std::__1::basic_string<char> &&>',而不是预期的const std::__1::basic_string<char> &&。在move_v2 中使用move_v2 或WhichType 本身似乎输出正确的东西。
但是,Clang 似乎也像我预期的 https://wandbox.org/permlink/Nv7yXnCbqxjJMVvX 那样对 std::move(v) 表达式进行重载解析。这让我的一些担忧消失了,但我仍然不明白 decltype() 在 lambda 中的行为。
在这种特殊情况https://wandbox.org/permlink/5mhrOzLn5XZO8LNB 中,GCC 似乎没有这种不一致。
如果我对 decltype() 的理解有误,有人可以纠正我,或者指出这个错误在 clang 中出现的确切位置吗?乍一看似乎有点吓人。当在 SFINAE 或类似的东西中使用时,这可能会导致问题。
【问题讨论】:
-
正确的结果应该是
const &&,因为非可变lambda的按值捕获值是const,所以你的理解是正确的。即使在const &&和&&:wandbox.org/permlink/ydV79sx7g7l2RcjB 之间,Clang 也能正确地进行重载解析,因此在实践中它不会造成太大问题。 -
@L.F.谢谢,我担心的是存在复杂的部分专业化链并且有人使用 decltype() 调度并选择适当的功能的情况。在这种情况下,他们可能会得到错误的结果。听起来也很难调试:(
-
@JVApen 我认为这也是我的理解——这似乎是一种边缘情况,编译器没有正确处理,或者根据我们对 decltype() 的理解,我们期望不正确。而且我对后者没有足够的信心做出任何判断。我希望对他们对标准的理解更有信心的人可以链接相关部分并将误解解释为答案。
-
我想这是clang的错误。一起使用
decltype时,const似乎作为引用的返回类型丢失了。
标签: c++ clang language-lawyer c++17 decltype