Search code examples
c++templatesvirtualabstractoption-type

Why can't I have std::optional<T> where T is abstract?


This does not work:

struct Type {
    virtual bool func(const std::string& val) const noexcept = 0;
}

// in main
optional<Type> = some_function_returning_optional_type();

and fails with a error message:

error: cannot declare field 'std::experimental::fundamentals_v1::_Optional_base<Type, false>::<anonymous union>::_M_payload' to be of abstract type 'Type'

Changing the Type to have a non-pure function works, but is not appropriate in this case, because there cannot be an instance of Type in my code, only classes which inherit from it should be able to exist.


Solution

  • std::optional<T> stores its value in-place - it therefore needs to know the size of T to work correctly, and T must be a concrete type that can be instantiated. You can think of std::optional<T> as:

    template <typename T>
    struct optional
    {
        std::aligned_storage_t<sizeof(T), alignof(T)> _data;
        bool _set;
    };
    

    An abstract type represents an interface - polymorphism and some sort of indirection are required to work with abstract types. std::optional doesn't have any indirection by design.