C++ 11标准说:
30.6.6类模板未来
(3)"调用除析构函数之外的任何成员函数,移动赋值运算符或对
valid() == false未定义的未来对象有效的效果 ."
那么,这是否意味着以下代码可能会遇到未定义的行为?
void wait_for_future(std::future<void> & f)
{
if (f.valid()) {
// what if another thread meanwhile calls get() on f (which invalidates f)?
f.wait();
}
else {
return;
}
}
Run Code Online (Sandbox Code Playgroud)
Q1:这真的是一种可能的未定义行为吗?
Q2:是否有任何符合标准的方法来避免可能的未定义行为?
请注意,该标准有一个有趣的注释[也在30.6.6(3)]:
"[注意:鼓励实现检测此情况并抛出类型为future_error的对象,错误条件为
future_errc::no_state.-endnote]"
问题3:如果我只依靠标准的说明并且只是在f.wait()没有检查f有效性的情况下使用它,这样可以吗?
void wait_for_future(std::future<void> & f)
{
try {
f.wait();
}
catch (std::future_error const & err) {
return;
}
}
Run Code Online (Sandbox Code Playgroud)
事实证明,我的例子的真正问题不是直接由于并行修改(get从单个线程调用单个修改,调用另一个线程valid并且wait应该是安全的).
真正的问题是std::future对象的 …
所有GCC 4.8.4,4.9.3,5.3.0都通过了测试std::exception(对于任何-std = c ++ 11/1y/14/1z/17选项,如果可用):
static_assert(std::is_nothrow_copy_constructible<std::exception>::value, "test exception");
static_assert(std::is_nothrow_copy_assignable <std::exception>::value, "test exception");
Run Code Online (Sandbox Code Playgroud)
这很好,因为std::exception没有特殊成员(C++ 14 18.8.1):
Run Code Online (Sandbox Code Playgroud)namespace std { class exception { public: exception() noexcept; exception(const exception&) noexcept; exception& operator=(const exception&) noexcept; virtual ~exception(); virtual const char* what() const noexcept; }; }
不幸的是,上面的所有编译器都失败了以下static_asserts:
static_assert(std::is_nothrow_copy_constructible<std::runtime_error>::value, "test runtime_error");
static_assert(std::is_nothrow_copy_assignable <std::runtime_error>::value, "test runtime_error");
Run Code Online (Sandbox Code Playgroud)
该标准仅包含std::runtime_error19.2.6中的以下内容:
Run Code Online (Sandbox Code Playgroud)namespace std { class runtime_error : public exception { public: explicit runtime_error(const string& what_arg); explicit runtime_error(const char* what_arg); }; }
但是没有任何关于 …
我使用从继承的类std::system_error进行错误处理,我想控制what()调用时返回的内容.原因:标准(C++ 11和草案C++ 1y CD - N3690,下面的§引用都是后者)没有说明返回的字符串究竟是what()什么样子,它只是在§19.5中给出了注释.6.2(14):
注意:返回的NTBS可能是内容
what_arg + ": " + code.message(). - 结束说明
所以它应被视为依赖于实现.(顺便说一句,不应该code().message()而不是code.message()?)
所以,问题是:what()如果我想要符合标准并且不依赖于实现(即想要是可移植的),我如何准确定义返回的字符串?
对于那些喜欢代码的人:
class my_class : public std::system_error {
public:
my_class(std::error_code ec, std::string const & what_arg)
: system_error(ec, /* this string is not required to be equal to what is returned by what() */)
{
// ok, try it here
// but what is the name of the member storing the string? …Run Code Online (Sandbox Code Playgroud) 我想使用单个(交叉)编译器来编译不同ARM调用约定的代码:因为我总是想使用浮点和NEON指令,我只想选择硬浮点调用约定或软浮点数(softfp)调用约定.
我的编译器默认为hard-float,但它支持我需要的两种架构:
$ arm-linux-gnueabihf-gcc -print-multi-lib
.;
arm-linux-gnueabi;@marm@march=armv4t@mfloat-abi=soft
$
Run Code Online (Sandbox Code Playgroud)
当我使用默认参数进行编译时:
$ arm-linux-gnueabihf-g++ -Wall -o hello_world_armhf hello_world.cpp
Run Code Online (Sandbox Code Playgroud)
它成功没有任何错误.
如果我使用-print-multi-lib返回的参数进行编译:
$ arm-linux-gnueabihf-g++ -marm -march=armv4t -mfloat-abi=soft -Wall -o hello_world hello_world.cpp
Run Code Online (Sandbox Code Playgroud)
它再次编译没有错误(顺便说一句,我如何测试结果代码是硬浮动还是软浮动?)
不幸的是,如果我试试这个:
$ arm-linux-gnueabihf-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -Wall -o hello_world hello_world.cpp
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: error: hello_world uses VFP register arguments, /tmp/ccwvfDJo.o does not
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: failed to merge target specific data of file /tmp/ccwvfDJo.o
collect2: error: ld returned 1 exit status
$
Run Code Online (Sandbox Code Playgroud)
我已经测试了一些参数的其他排列,但似乎除了-print-multi-lib所示的组合之外的任何其他结果都会导致错误.
我读过ARM编译错误,VFP注册使用的是可执行文件,而不是目标文件,但问题是二进制文件的某些部分是软的,有些是硬浮动的.我有一个C++文件来编译...
我错过了哪些参数可以用-march = armv7 -a -mthumb-interwork -mfloat-abi = softfp …