'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.

Example:

#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