【发布时间】: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.9 和 clang 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
我以前使用过这个(不知道我的不合格代码)来存储种子的副本以用于日志记录。*
我想知道:
为什么
seed_seq不可复制?这是我第一次遇到
g++和clang不符合标准。偏离标准是有意识的决定,还是实施错误?这有多普遍?我想了解更多。
* 我意识到我认为 seed_seq 是错误的,如果我只对 seed_seq::param 值(seed_seeq 的初始种子值)感兴趣,我应该保留我的副本vector<T>,而不是用于生成整数的类型。
【问题讨论】:
-
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暗示)。因此,需求表没有施加CopyConstructible或CopyAssignable等要求。[.. .]" -
另外,“[编者注:已插入本段以解决 LWG 问题 1069。但是,尚不清楚 (a) 这是否是一个好主意,以及 (b) 为什么应该使用这种类型为满足未对其他种子序列类型强加的要求。]”。看起来逻辑是 1)没有理由要求种子序列通常是可复制/可移动的; 2) 没有理由让
seed_seq做的超出一般种子序列的要求,所以 3) 删除了复制功能。