martinmoene/optional-lite

nonstd::optional is not a literal type

maikel opened this issue · 6 comments

I am looking for C++14 optional drop-in which I can use in constexpr contexts. From the Readme it seems to fit my needs, because you state this implementation provides a LiteralType in that case. I tried to compile

int main()
{
  constexpr nonstd::optional<int> o = 2;
}

with std=c++14 two different compilers (gcc-8 and clang-5) and both failed to compile the code.

While trying to fix the issue with custom patches I encountered following problems:

To make the type satisfy std::is_literal_type (deprecated, I know)

  • I had to make the destructor of optional trivial for trivially destructible types T. This can be achieved by inheriting from a base class and using a template specialization.
  • I had to mark at least on constructor of storage constexpr

To make the type usuable in constexpr contexts:

  • placement new in storage_t is not constexpr, so nonstd::optional with this storage implementation is not going to be usable in constexpr contexts.

Did i misunderstand something terribly wrong and/or do you think it would be worthwhile to provide some patches to target the above points.

Thanks for your analysis,

Indeed nonstd::optional may have been intended to be a literal type under C++11/14, but clearly is not so now (as tests would have revealed :(.

To note: your example does compile with std::optional.

I'd welcome improvements you suggest to constexpr-ness of nonstd::optional.

See also:

See:

Proposal to copy the is_trivially_destructible property for the optional:

  1. replace the destructor of the optional with some normal(protected) member method.
  2. replace the "using optional_lite::optional" with:
class optional_destruction_helper : public optional_lite::optional<T>
{
    using optional_lite_base= optional_lite::optional<T>;
public:
    using optional_lite_base::optional_lite_base;
};
template<typename T>
class optional_destruction_helper <T, true> : public optional_lite::optional<T>
{
    using optional_lite_base= optional_lite::optional<T>;
public:
    using optional_lite_base::optional_lite_base;
    ~optional_destruction_helper ()
    {
        optional_lite_base::destroy();
    }
};
template<typename T>
class optional : public optional_destruction_helper <T, !std::is_trivially_destructible<T>::value>
{
    using optional_lite_base= optional_destruction_helper <T, !std::is_trivially_destructible<T>::value>;
public:
    using optional_lite_base::optional_lite_base;
};

Thanks for your suggestion. May take a couple of weeks before i can address it.