I am trying to understand the behavior of "Type Erasure" by using std::make_shared. The basic idea is to use a class Object to wrap some different classes, such as class Foo and class Bar.
I write the following code, and it does work.
// TypeErasure.cpp
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Base
{
public:
    virtual ~Base() {}
    virtual std::string getName() const = 0;
};
template< typename T >
struct Derived : Base
{
public:
    explicit Derived(const T&& t) : objD(t) {}
    std::string getName() const override
    {
        return objD.getName();
    }
private:
    T objD;
};
class Object
{
public:
    template <typename T>
    explicit Object(T&& t)
        : objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}
    std::string getName() const
    {
        return objPtr->getName();
    }
    std::shared_ptr<const Base> objPtr;
};
void printName(std::vector<Object> vec)
{
    for (auto v: vec) std::cout << v.getName() << std::endl;
}
class Bar
{
public:
    std::string getName() const
    {
        return "Bar";
    }
};
class Foo
{
public:
    std::string getName() const
    {
        return "Foo";
    }
};
int main()
{
    std::vector<Object> vec{Object(Foo()), Object(Bar())};
    printName(vec);
}
but when I change "struct Derived : Base" into "class Derived : Base", it shows the following error.
error: no matching function for call to 'std::shared_ptr::shared_ptr(std::shared_ptr)'|
The code is as following.
// TypeErasure.cpp
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Base
{
public:
    virtual ~Base() {}
    virtual std::string getName() const = 0;
};
template< typename T >
class Derived : Base
{
public:
    explicit Derived(const T&& t) : objD(t) {}
    std::string getName() const override
    {
        return objD.getName();
    }
private:
    T objD;
};
class Object
{
public:
    template <typename T>
    explicit Object(T&& t)
        : objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}
    std::string getName() const
    {
        return objPtr->getName();
    }
    std::shared_ptr<const Base> objPtr;
};
void printName(std::vector<Object> vec)
{
    for (auto v: vec) std::cout << v.getName() << std::endl;
}
class Bar
{
public:
    std::string getName() const
    {
        return "Bar";
    }
};
class Foo
{
public:
    std::string getName() const
    {
        return "Foo";
    }
};
int main()
{
    std::vector<Object> vec{Object(Foo()), Object(Bar())};
    printName(vec);
}
What is the root cause of this error? Is it about the difference between class and struct? Is it because class is a reference and struct is a value?
 
    