'using c++ aggregate initialization in std::make_shared
Per my understanding, the following code constructs an object of type Foo and then moves that object into the memory allocated by 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' });
}
Is it possible to aggregate initialize Foo directly into the memory allocated by std::make_shared?
Solution 1:[1]
The inheritance solution feels a bit overkill to me, and adds a bit of readability confusion because the make_shared template is not your type.
Unaware readers might be confused about this aggregate_adapter part.
Here is an alternative:
#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');
}
Solution 2:[2]
I don't know of a way to make std::make_shared work here. However, one can construct a shared_ptr from an rvalue even for objects with private constructors and no copy or move constructors using a new-expression, where the initializer is a braced-init-list.
#include <memory>
class A {
private:
A() {}
public:
A(const A&) = delete;
A(A&&) = delete;
static A construct() {
return A();
}
};
int main() {
auto a = std::shared_ptr<A>(new A{A::construct()});
}
In this situation, @melak47's answer does not work as it depends on rvalue references and needs a working move constructor.
A real-world example of such a situation would be exposing an iterator-type class designed to be only constructed locally as a Python object via pybind11.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | GARCIN David |
| Solution 2 | heiner |
