【发布时间】:2017-11-07 21:48:00
【问题描述】:
我的程序中几乎整天都丢失了跟踪错误。出于某种原因,我在 c++11 中对 std::apply 的实现是错误的:底层函数的参数在调用过程中以某种方式得到了 empty。很好的例子是std::unique_ptr,在调用临时函数(下面是foo())后,在被调用函数的主体中总是empty()。
我已将我的代码简化为一个简单的测试用例:
#include <tuple>
#include <memory>
#include <iostream>
struct Foo
{
Foo()
{
std::cout << "Foo()" << std::endl;
}
~Foo()
{
std::cout << "~Foo()" << std::endl;
}
};
template <typename ...Args>
void foo(Args && ...args)
{
using TupleType = decltype(std::make_tuple(std::forward<Args>(args)...));
std::cout << "Point #1" << std::endl;
/// Package arguments to a function.
auto && packaged_args = std::make_shared<TupleType>(std::make_tuple(std::forward<Args>(args)...));
std::cout << "Point #2" << std::endl;
}
int main()
{
std::unique_ptr<Foo> foo_var{new Foo};
foo(std::move(foo_var));
return 0;
}
如果使用 clang 和 libc++ (-stdlib=libc++) 编译,结果是:
Foo()
Point #1
~Foo()
Point #2
coliru.stacked-crooked.com 上的实时示例
结果显然不正确。如果用clang, but without libc++编译,或者用gcc编译,结果如预期:
Foo()
Point #1
Point #2
~Foo()
我发现 clang 和 libc++ 的组合有一个可笑的解决方法,替换为:
auto && packaged_args = std::make_shared<TupleType>(std::make_tuple(std::forward<Args>(args)...));
与:
std::shared_ptr<TupleType> packaged_args{new TupleType(std::make_tuple(std::forward<Args>(args)...))};
它再次按预期工作。
coliru.stacked-crooked.com 上的实时示例
问题是:它是一个 UB,所以两个编译器都对错误的代码或代码是正确的,这是一个错误?
【问题讨论】:
-
今晚开始调试。 PS 我们也有 bugzilla :-P
-
Coliru 的 Clang 是 3.8。似乎在 Wandbox 的 3.9.1 中已修复。
-
@EricWF,抱歉没有在此处发布目录,我不能 100% 确定我的程序没有缺陷。
-
FWIW 似乎这个问题只发生在真正旧版本的 libc++ 上。针对主干进行测试,问题不会重现。
-
@EricWF,很遗憾,它会影响内置的
FreeBSD 11.0-STABLE附带的版本。
标签: c++ c++11 templates clang libc++