Возврат шаблонного интеллектуального указателя из вызовов, похожих на конструктор - PullRequest
0 голосов
/ 16 октября 2019

Я хочу написать некоторую простую для вызова инициализацию объекта, и я хотел бы, чтобы эти объекты были shared_ptr MyClass.

Просто для наглядности представьте себе этот класс:

class MyClass
{
public:
  MyClass(int number);
  MyClass(wxString path);
}

int main()
{
  //For now, objects are created in c style like this:
  MyClass obj1("C:\\test");
  MyClass * obj2 = new MyClass(5);
}

Теперь я хотел бы изменить это с помощью простой в использовании интеллектуальной инициализации указателя. Моя цель - что-то похожее на вызов конструктора, так что очень мало нужно изменить, чтобы обновить старый вызов новым:

Smart_MyClass obj1("C:\\test");
Smart_MyClass obj2(5);
//where Smart_MyClass is std::shared_ptr<MyClass> 

Я мог бы решить это с помощью функции:

template<typename T>
inline Smart_MyClass Smart_MyClass_Fct(T t)
{
    return std::make_shared<MyClass>(t);
};

Smart_MyClass obj = Smart_MyClass_Fct(7);

Как я могу перевести это в нужную мне форму? Я мог бы подумать об использовании оператора (), который потребовал бы структуру / класс и, возможно, наследование моего фактического класса? И, возможно, приведение его обратно в родительский класс? Уверен, что есть что-то более элегантное. ;-)

1 Ответ

0 голосов
/ 16 октября 2019

Вы можете попробовать что-то вроде этого:

template<typename T>
class SharedWrapper
{
public:
    template<typename... Args>
    SharedWrapper(Args... args) : 
        m_p{std::make_shared<T>(std::forward<Args>(args)...)}
    { }

    T& operator*() const noexcept { return *m_p; }
    T* operator->() const noexcept { return m_p.operator->(); }
    explicit operator bool() const noexcept { return static_cast<bool>(m_p); }

private:
    std::shared_ptr<T> m_p;
};

Это просто перенаправляет аргументы конструктора в функции make_shared, а затем отражает интерфейс интеллектуального указателя. (Здесь вам может потребоваться добавить дополнительные методы пересылки по мере необходимости.)

С помощью:

using Smart_MyClass = SharedWrapper<MyClass>;

вы должны получить желаемое поведение и также можете использовать его для разных классов.

Однако я не вижу возможности иметь Smart_MyClass на самом деле std::shared_ptr<MyClass>. Наследование от shared_ptr не рекомендуется, поскольку у него нет виртуального деструктора. Это также может ограничить удобство использования этого подхода.

Есть ли какая-либо причина помимо стиля, которая заставляет вас хотеть использовать эту нотацию?

...