【问题标题】:Why is std::seed_seq non-copyable according to C++11, and why doesn't gcc/clang conform?为什么 std::seed_seq 根据 C++11 是不可复制的,为什么 gcc/clang 不符合?
【发布时间】:2015-03-30 15:21:53
【问题描述】:

考虑以下最小示例:

// main.cpp
#include <random>

int main(int, char **)
{
  std::seed_seq seed1{1337, 42};
  std::seed_seq seed2(seed1);
  std::seed_seq seed3 = seed2;
  return 0;
}

根据 C++ 标准,这不应该编译,因为std::seed_seq 既不是copy constructible,也不是copy assignable

但是,g++ 4.9clang 3.4 都可以正常编译

g++-4.9 -std=c++11 -Wall main.cpp
clang++ -std=c++11 -Wall main.cpp

android ndk 的llvm-libc++ 实现似乎遵循seed_seq 的“不可复制”属性。可以在源中确认

 android-ndk-r10d/sources/cxx-stl/llvm-libc++/libcxx/include/random:3553

或者通过使用编译最小示例

 ${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ \
 -std=c++11 -c -Wall \
 -I${NDK_HOME}/sources/cxx-stl/llvm-libc++/libcxx/include \
 -I${NDK_HOME}/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/include \
 -I${NDK_HOME}/sources/cxx-stl/llvm-libc++/../../android/support/include \
 -isystem ${NDK_HOME}/platforms/android-18/arch-arm/usr/include \
 main.cpp

我以前使用过这个(不知道我的不合格代码)来存储种子的副本以用于日志记录。*

我想知道:

  1. 为什么seed_seq 不可复制?

  2. 这是我第一次遇到g++clang 不符合标准。偏离标准是有意识的决定,还是实施错误?这有多普遍?我想了解更多。


* 我意识到我认为 seed_seq 是错误的,如果我只对 seed_seq::param 值(seed_seeq 的初始种子值)感兴趣,我应该保留我的副本vector&lt;T&gt;,而不是用于生成整数的类型。

【问题讨论】:

  • gcc 和 clang 通常使用相同的 C++ 库实现 (libstdc++),因此当其中出现问题时,它们将在 gcc 或 clang 中可见。这并不意味着两个独立的实现者认为这是一个好主意。
  • This program correctly does not compile with libc++,所以这是一个 libstdc++ 问题。
  • 报告为bug 65631。对于“为什么它不可复制”,我们可能不得不挖掘出做出改变的论文/问题。从LWG issue 972来看,原来不是这样的。
  • open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3037.pdf :“首先,要求可复制性的概念是错误的(由Semiregular 暗示)。因此,需求表没有施加CopyConstructibleCopyAssignable 等要求。[.. .]"
  • 另外,“[编者注:已插入本段以解决 LWG 问题 1069。但是,尚不清楚 (a) 这是否是一个好主意,以及 (b) 为什么应该使用这种类型为满足未对其他种子序列类型强加的要求。]”。看起来逻辑是 1)没有理由要求种子序列通常是可复制/可移动的; 2) 没有理由让seed_seq 做的超出一般种子序列的要求,所以 3) 删除了复制功能。

标签: c++ c++11 g++ libstdc++


【解决方案1】:

对于那些在未来看到这一点的人,根据 T.C.和 ecatmur,这是libstdc++ bug 65631。不过,没有预计到达时间。该行为符合原始提案,但根据N3037 paper,此行为已更改为从概念中删除可复制性以解决 LWG 问题 1069。

【讨论】:

  • 添加一个回答问题的人所执行的操作概述的答案感觉很奇怪。 (例如发布错误 65631,挖掘 N3037 论文)。我敢肯定,那些在未来看到这一点的人,也会看到那些 cmets。我想有一个总结并没有什么坏处。
  • @swalog -- 是的,有一个总结很好;此外,让一个问题悬而未决真的没有意义,而 cmets 加起来就是一个答案 :) 你宁愿我制作这个社区 wiki 吗?
  • 我对此没有任何欲望、赌注或发言权 :-) 随你便。但是,既然您提出了要求,那么在应得的情况下给予信用似乎是合适的。
猜你喜欢
  • 2013-05-17
  • 1970-01-01
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 2013-02-03
  • 2014-08-30
相关资源
最近更新 更多