g++ 6.1 可能 std::forward 回归 - 错误或预期行为?
Possible std::forward regression with g++ 6.1 - bug or intended behavior?
g++ 6.1 最近被引入到 Arch Linux 的测试库中,我的一些使用 g++ 5.3.0 成功编译的代码不再编译。我做了一个最小的例子:
// This code compiles with g++ 5.3.0
// This does not compile with g++ 6.1
#include <type_traits>
#include <utility>
#include <tuple>
#define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
struct sinker
{
template <typename T>
void sink(T&)
{
}
};
template <typename T, typename TF>
void caller(T& v, TF&& f)
{
sinker s;
f(s, v);
}
template <typename T>
void interface(T& v)
{
return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)
{
xs.sink(FWD(xv));
});
}
int main()
{
int x = 0;
interface(x);
}
这是报告的错误:
: In instantiation of ‘get_impl(T&)::<lambda(auto:1&, auto:2&&)> [with auto:1 = sinker; auto:2 = int; T = int]’:
:25:58: required by substitution of ‘template<class auto:1, class auto:2> get_impl(T&)
[with T = int]::<lambda(auto:1&, auto:2&&)>::operator
decltype (((get_impl(T&) [with T = int]::<lambda(auto:1&, auto:2&&)>)0u).operator()(static_cast<auto:1&>(<anonymous>),
static_cast<auto:2&&>(<anonymous>))) (*)(auto:1&, auto:2&&)() const [with auto:1 = sinker; auto:2 = int]’
:19:6: required from ‘void chunk_fn_impl(T&, TF&&) [with T = int; TF = get_impl(T&) [with T = int]::<lambda(auto:1&, auto:2&&)>]’
:25:25: required from ‘void get_impl(T&) [with T = int]’
:36:15: required from here
:27:13: error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
xs.sink(FWD(md));
^~
:10:10: note: initializing argument 1 of ‘void sinker::sink(T&) [with T = int]’
void sink(T&)
^~~~
变化中:
return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)
至:
return caller(v, [](auto& xs, auto& xv) -> decltype(auto)
允许代码成功编译。
我不明白为什么会发生此错误,因为 xv
正在被完美转发并且 FWD(xv)
调用应该产生一个左值引用。请注意,代码在 g++ 5.3.0 和 clang++ 3.7 中按预期工作。
(尝试使用多个 g++ 版本编译并将 auto&&
更改为 auto&
。)
这是 g++ 6.1 错误吗? 还是代码使用以前版本的 g++ 和 clang++ 编译不正确?
这是一个 g++ 前端错误:该问题被报告为 bug 70942。
g++ 6.1 最近被引入到 Arch Linux 的测试库中,我的一些使用 g++ 5.3.0 成功编译的代码不再编译。我做了一个最小的例子:
// This code compiles with g++ 5.3.0
// This does not compile with g++ 6.1
#include <type_traits>
#include <utility>
#include <tuple>
#define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
struct sinker
{
template <typename T>
void sink(T&)
{
}
};
template <typename T, typename TF>
void caller(T& v, TF&& f)
{
sinker s;
f(s, v);
}
template <typename T>
void interface(T& v)
{
return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)
{
xs.sink(FWD(xv));
});
}
int main()
{
int x = 0;
interface(x);
}
这是报告的错误:
: In instantiation of ‘get_impl(T&)::<lambda(auto:1&, auto:2&&)> [with auto:1 = sinker; auto:2 = int; T = int]’:
:25:58: required by substitution of ‘template<class auto:1, class auto:2> get_impl(T&)
[with T = int]::<lambda(auto:1&, auto:2&&)>::operator
decltype (((get_impl(T&) [with T = int]::<lambda(auto:1&, auto:2&&)>)0u).operator()(static_cast<auto:1&>(<anonymous>),
static_cast<auto:2&&>(<anonymous>))) (*)(auto:1&, auto:2&&)() const [with auto:1 = sinker; auto:2 = int]’
:19:6: required from ‘void chunk_fn_impl(T&, TF&&) [with T = int; TF = get_impl(T&) [with T = int]::<lambda(auto:1&, auto:2&&)>]’
:25:25: required from ‘void get_impl(T&) [with T = int]’
:36:15: required from here
:27:13: error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
xs.sink(FWD(md));
^~
:10:10: note: initializing argument 1 of ‘void sinker::sink(T&) [with T = int]’
void sink(T&)
^~~~
变化中:
return caller(v, [](auto& xs, auto&& xv) -> decltype(auto)
至:
return caller(v, [](auto& xs, auto& xv) -> decltype(auto)
允许代码成功编译。
我不明白为什么会发生此错误,因为 xv
正在被完美转发并且 FWD(xv)
调用应该产生一个左值引用。请注意,代码在 g++ 5.3.0 和 clang++ 3.7 中按预期工作。
(尝试使用多个 g++ 版本编译并将 auto&&
更改为 auto&
。)
这是 g++ 6.1 错误吗? 还是代码使用以前版本的 g++ 和 clang++ 编译不正确?
这是一个 g++ 前端错误:该问题被报告为 bug 70942。