根据我的理解,下面的代码构造一个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
分配的内存中?
答案 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');
}