clang + libc ++:make_tuple与make_shared的组合导致早期对象破坏

时间:2017-06-06 18:34:29

标签: c++ c++11 templates clang libc++

我的程序中几乎整天都没有跟踪错误。出于某种原因,我在c ++ 11方面的std::apply实现是错误的:底层函数的参数在调用过程中以某种方式得到为空。好的例子是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

上的实例

qustion是:它是一个UB,所以两个编译器都是正确的错误代码或代码是好的,这是一个错误?

1 个答案:

答案 0 :(得分:2)

这似乎是libc ++的元组实现中的一个错误。

该错误存在于Libc ++&lt; = 3.8中,但已在3.9中通过我的元组重写修复。

抱歉这个错误;它似乎是避免升级的最好/唯一方法。