Буст опционально распознает наследование?

class Base {};
class Derived : public Base {};

void func(boost::optional<Base>&) {}

int main () {
  boost::optional<Derived> x;
  func(x);
}

Примет ли func оба варианта: базовый и производный?

2 ответа

Решение

Нет, это не сработает. func принимает lvalue ссылку на boost::optional<Base>, Это означает, что он может принимать lvalue типа boost::optional<Base>lvalue типа, который происходит публично и однозначно из boost::optional<Base>или какой-то другой тип, который имеет operator boost::optional<Base>&(), Ничто из этого не относится к boost::optional<Derived>, Шаблоны классов не ковариантны в системе типов C++ - boost::optional<Derived> не наследуется от boost::optional<Base>,


Это была бы другая история, если бы func принял его аргумент по значению. Если бы это выглядело так:

void func(boost::optional<Base> ) { }

В этом случае вы можете позвонить func с boost::optional<Derived>, Но этот конвертирующий конструктор помечен explicitтак что вам придется написать:

func(boost::optional<Base>{x});

Хорошо, что это явно - вы отмечаете, что вы (потенциально) нарезаете x,

Даже если это сработает (что, скорее всего, покупка, я не проверял), это приведет к нарезке. Только Base часть будет храниться в необязательном порядке.

опционально содержит внутренний буфер размера, необходимого для хранения Base, И даже если Base будет того же размера, что и Derived (как в вашем случае) все равно он будет хранить только Base,


РЕДАКТИРОВАТЬ:

Выше был дан ответ на оригинальный вопрос, который содержал следующий код:

int main () {
  boost::optional x(Derived());
  func(x);
}

Такой код неверен по двум причинам:

  1. boost::optional требует аргумента шаблона
  2. Даже с аргументом шаблона это все равно будет объявление функции.

Я проигнорировал эти проблемы и предположил, что нечто подобное подразумевалось:

int main () {
  boost::optional<Base> x = Derived();
  func(x);
}

Хотя этот код компилируется (по крайней мере, Visual Studio 2013 и Boost 1.60) и вызывает нарезку. Как видно, запустив следующую программу:

#include <boost/optional.hpp>
#include <iostream>

class Base
{
public:
    virtual ~Base() { std::cout << "~Base" << std::endl; }
};

class Derived : public Base
{
public:
    virtual ~Derived() { std::cout << "~Derived" << std::endl; }
};

int main()
{
    boost::optional<Base> x = Derived();
}

который производит продукцию

~Derived
~Base
~Base

Второй ~Base показывает, что optional destroyes Base объект, а не Derived объект. (The ~Derived от временного объекта Derived() как первый ~Base.)

Другие вопросы по тегам