【问题标题】:Possible std::forward regression with g++ 6.1 - bug or intended behavior?g++ 6.1 可能的 std::forward 回归 - 错误或预期行为?
【发布时间】:2016-08-29 15:04:19
【问题描述】:

g++ 6.1 最近被引入 Arch Linux 的测试存储库,我使用 g++ 5.3.0 成功编译的一些代码不再编译。我做了一个最小的例子:

gcc.godbolt.org link

// 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 中按预期工作。

gcc.godbolt.org link

(尝试使用多个 g++ 版本进行编译并将auto&amp;&amp; 更改为auto&amp;。)

这是 g++ 6.1 的错误吗? 或者代码是否使用以前版本的 g++ 和 clang++ 编译错误?

【问题讨论】:

  • forward 无关。这看起来像一个前端错误。
  • auto&amp;&amp; 表示 lambda 是一个模板,需要参数类型推导。但caller 也是如此。我不明白这怎么可能编译,它应该被困在无限递归的参数类型推导中。至少根据我对 auto&amp;&amp; 的 lambdas 的原始理解。有人请解释为什么这应该有效。
  • @T.C.报告为bug 70942
  • @sp2danny:为什么会有递归? interface 调用 caller,后者调用通用 lambda。然后 lambda 调用 sink。这里没有循环。类型推导只发生一次。
  • 这似乎只影响具有推断返回类型的无捕获通用 lambda。

标签: c++ gcc lambda c++14 perfect-forwarding


【解决方案1】:

这是一个 g++ 前端错误:该问题被报告为 bug 70942

【讨论】:

    猜你喜欢
    • 2016-09-26
    • 2016-11-27
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多