在std :: make_shared中使用c ++聚合初始化

时间:2016-02-09 18:02:42

标签: c++ c++11

根据我的理解,下面的代码构造一个Foo类型的对象,然后将该对象移动到由std::make_shared分配的内存中

struct Foo
{
    std::string s;
    int i;
    char c;
};

int main(int argc, char* argv[])
{
    auto foo = std::make_shared<Foo>(Foo{"hello", 5, 'c' });
}

是否可以将aggregate initialize Foo直接插入std::make_shared分配的内存中?

2 个答案:

答案 0 :(得分:10)

您可以创建一个带有可变参数构造函数模板的适配器来转发参数,例如:

template<class T>
struct aggregate_adapter : public T {
    template<class... Args>
    aggregate_adapter(Args&&... args) : T{ std::forward<Args>(args)... } {}
};

然后你可以这样做:

auto foo = std::make_shared<aggregate_adapter<Foo>>("hello", 5, 'c');

由于aggregate_adapter<Foo>Foo相关,foo也可转换为std::shared_ptr<Foo>

注意事项

不幸的是,转发的使用也使得无法在没有明确指定类型的情况下对std::make_shared<aggregate_adapter<Foo>>({'h','e','l','l','o'}, 5, 'c');之类的任何成员进行括号初始化,但同样的限制也适用于make_shared。

答案 1 :(得分:1)

对我来说,继承解决方案有点过大,并且由于make_shared模板不是您的类型,因此增加了一些可读性混乱。

Unaware读者可能对这个aggregate_adapter部分感到困惑。

这里是另一种选择:

#include <iostream>
struct Foo
{
    std::string s;
    int i;
    char c;
};

template<typename T, typename... Args>
std::shared_ptr<T> MakeAggregateShared(Args&&... args)
{
    return std::make_shared<T>(T{ std::forward<Args>(args)... });
}

int main(int argc, char* argv[])
{
    auto foo = MakeAggregateShared<Foo>("hello", 5, 'c');
}