Как сделать уникальные указатели на полиморфные классы, используя тернарный оператор? - PullRequest
3 голосов
/ 28 октября 2019

Я пытаюсь установить переменную, используя троичный оператор. Однако компилятор жалуется на несовместимые типы. Я уверен, что есть способ сделать это. Я пробовал статическое приведение к базовому классу, но мне не удалось получить правильный синтаксис.

#include <iostream>
#include <memory>
struct A
{
    virtual ~A() = default;
    virtual void test() {std::cout << "A" << std::endl;} 
};

struct B: public A
{
    void test() final {std::cout << "B" << std::endl;} 
};

struct C: public A
{
    void test() final {std::cout << "C" << std::endl;} 
};

int main()
{
    bool t = true;
    // Try to cast try a base unique class ptr. Maybe use static_cast??
    std::unique_ptr<A> aptr = t ? std::make_unique<B>(): std::make_unique<C>();
    aptr->test();
}

Ответы [ 2 ]

3 голосов
/ 28 октября 2019

Возвращаемое значение троичного выражения является общим типом обоих выражений (на самом деле std::common_type может использовать троичный оператор как часть его реализации :-)).

В то время как std::unique_ptr<B> и std::unique_ptr<C> являютсянесвязанные типы,

и std::unique_ptr<B> и std::unique_ptr<C> могут быть преобразованы в std::unique_ptr<A>, поэтому достаточно явно преобразовать один из них:

auto aptr = t ? std::unique_ptr<A>{std::make_unique<B>()}
              : std::make_unique<C>();

Демо

2 голосов
/ 28 октября 2019

Попробуйте это:

std::unique_ptr<A> aptr = t ? std::unique_ptr<A>(new B()): std::unique_ptr<A>(new C());
...