gpt4 book ai didi

c++ - `pair::operator=(pair&&)` 错误与 `auto&` 推断 move 操作 - libstdc++ 回归?

转载 作者:IT老高 更新时间:2023-10-28 22:05:11 26 4
gpt4 key购买 nike

鉴于这个程序:

struct Val
{
Val() = default;
Val(Val&&) = default;
auto& operator=(Val&&);
};

/* PLACEHOLDER */

auto& Val::operator=(Val&&) { return *this; }

替换 /* PLACEHOLDER */与...

int main()
{
std::vector<std::pair<int, Val>> v;
v.emplace(std::begin(v), 0, Val{});
}

...编译成功:

  • g++ 6.2.0
  • g++ 6.3.0
  • g++ 7.0.1(主干)

  • clang++ 3.9.1

  • clang++ 5.0.0 (HEAD)

on wandbox


替换 /* PLACEHOLDER */与...

template <typename TVec>
void a(TVec& v)
{
v.emplace(std::begin(v), 0, Val{});
}

int main()
{
std::vector<std::pair<int, Val>> v;
a(v);
}

...编译成功:

  • g++ 6.2.0
  • clang++ 3.9.1

...但在以下位置产生编译时错误:

  • g++ 6.3.0
  • g++ 7.0.1(主干)
  • clang++ 5.0.0 (HEAD)

on wandbox


产生的错误似乎与受约束的 pair operator=(pair&&) 有关过载 - from include/bits/stl_pair.h on GitHub's libstdc++ mirror :

  pair&
operator=(typename conditional<
__and_<is_move_assignable<_T1>,
is_move_assignable<_T2>>::value,
pair&&, __nonesuch&&>::type __p)
noexcept(__and_<is_nothrow_move_assignable<_T1>,
is_nothrow_move_assignable<_T2>>::value)
{
first = std::forward<first_type>(__p.first);
second = std::forward<second_type>(__p.second);
return *this;
}
  • 代入is_move_assignable<_T2>std::true_type允许代码编译。

  • move Val::operator=(Val&&)的定义之前 /* PLACEHOLDER */允许代码编译。

  • 更改 auto& Val::operator=(Val&&)Val& Val::operator=(Val&&)允许代码编译。

这是怎么回事?这是最新版本的 libstdc++ 中的实现缺陷吗?还是旧版本错误地编译了格式错误的代码?


编辑:如 AndyG在他的 (现已删除) 答案中发现,在调用 emplace 之前调用空函数时也会发生错误。 :

template <typename TVec>
void a(TVec&) { }

int main()
{
std::vector<std::pair<int, Val>> v;
a(v);
v.emplace(std::begin(v), 0, Val{});
}

退出a(v);以上可防止产生编译时错误。 这种行为在 g++7 和 clang++5 中都存在。

on wandbox


Sergey Murzin 发现了另一个奇怪的案例,并且可以测试出on wandbox :

int main()
{
std::vector<std::pair<int, Val>> v;
v.emplace(v.begin(), 0, Val{});
std::cout << v.back().first << std::endl;
}

上面的代码会产生编译错误。注释掉包含 std::cout 的行防止错误发生。 这种行为在 g++7 和 clang++5 中都存在。

最佳答案

这几乎可以肯定是实例化点问题。如果你做了一些触发 pair<int, Val> 的实例化的事情的定义在 main ,然后你得到错误。否则,它只会在 vector::emplace 时被实例化。被实例化,这里讨论的实现推迟到翻译单元的末尾(这是允许的,请参阅 [temp.point]/8 ),此时赋值运算符已完全定义并可调用。

a(v)触发 pair<int, Val> 定义的实例化因为 ADL 需要它。如果你写 ::a(v)(a)(v) (都抑制 ADL)然后错误消失。 (很明显,a.back().first 需要 pair<int, Val> 的实例化:您正在访问它的数据成员。)

关于c++ - `pair::operator=(pair&&)` 错误与 `auto&` 推断 move 操作 - libstdc++ 回归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41956691/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com