0

Why doesn’t std::make_shared work anymore when the class Widget inherits class enable_shared_from_this?

Here is the code snippet:

#include<memory>
#include<vector>
#include<iostream>

class Widget:public std::enable_shared_from_this<Widget>
{
public:
    std::vector<int> vec;
    int var;
};

int main()
{
    auto wp{std::make_shared<Widget>()}; 
    //auto wp1{std::make_shared<Widget>(std::vector{1,2,3}, 9)}; //why his line compiles if class Widget does not inherit class enable_shared_from_this<Widget> 
}

What's more, auto wp1{std::make_shared<Widget>(std::vector{1,2,3}, 9)}; works well if you remove the inheritance.

UPDATED: Both the aforementioned code snippet do not compile with clang.

John
  • 2,963
  • 11
  • 33

1 Answers1

1

TED's answer:

It's because there is a constructor added by enable_shared_from_this which removes the possibility to do aggregate initialization. In order to support creating it from make_shared, add the necessary constructors:

public:
    Widget() = default;
    Widget(const std::vector<int>& v, int i) : vec(v), var(i) {}

It works indeed. But I still don't know why there is a constructor added by enable_shared_from_this?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
John
  • 2,963
  • 11
  • 33
  • "*I still don't know why there is a constructor added by `enable_shared_from_this`*" - It is because [`std::enable_shared_from_this`](https://en.cppreference.com/w/cpp/memory/enable_shared_from_this) contains a `std::weak_ptr` member that has to be initialized. – Remy Lebeau May 15 '22 at 18:47
  • @RemyLebeau Thank you for the clarification. But I still have a question. Since it is ***`std::enable_shared_from_this` other than `Widget` that contains a `std::weak_ptr`***, should not the said `std::weak_ptr` be initialized in the constructor of the base calss(i.e. `std::enable_shared_from_this`) other than the constructor of the derived class? If I am wrong, please let me know. – John May 16 '22 at 01:39
  • Yes, the `weak_ptr` is initialized in the base class constructor, but [base class constructors are not inherited by derived classes by default](https://stackoverflow.com/questions/347358/). So your `Widget` derived from `enable_shared_from_this` does not have constructors that match your `make_shared()` call unless you explicitly add those constructors to `Widget`. – Remy Lebeau May 16 '22 at 03:38
  • @RemyLebeau The question why the inheritance to class `std::enabled_from_this` would suppress the constructor which exists if there is no such inheritance.You see https://godbolt.org/z/M99asbav1 works. – John May 16 '22 at 04:41
  • What exactly is unclear about this? Without the inheritance, `Widget` is an aggregate, and the `make_shared()` statement you are asking about uses aggregate initialization. With the inheritance, `Widget` is not an aggregate, so the `make_shared()` statement requires a constructor to call, which is not inherited. – Remy Lebeau May 16 '22 at 07:45