Search code examples
c++design-patternsboost-variantstate-patternboost-optional

Difference between std::optional and boost::optional when its value is a variant


In embedded programming memory allocations are things that we want to avoid. So using design patterns like state design pattern is cumbersome. If we know how many states we will have then we can use placement new operations. But in this article the functional approach avoids all memory manipulations. Only drawback is that it is only for users that have C++17 availability. I tried to use boost::variant and boost::optional with c++11, but a conversion operator is missing like in in this minimal example (Here with MSVC with c++17 it compiles but not with std latest):

#include <string>
#include <boost/variant.hpp>
#include <boost/optional.hpp>


boost::optional<boost::variant<int, std::string>> f()
{
   return 5;
}


int main()
{
    auto ret = *f();
    return *boost::get<int>(&ret);
}

Error message:

error: no viable conversion from returned value of type 'int' to function return type 'boost::optional<boost::variant<int, std::string>>' (aka 'optional<variant<int, basic_string<char>>>')
return 5;

But if I replace boost::optional with std::optional it compiles fine: compiling example Can somebody explain what is the difference between them, and how can I make it work with boost also?


Solution

  • boost::optional doesn't have a constructor that takes arguments to pass to the underlying type but std::optional does (see constructor number 8)

    You need to explicitly call the optional constructor:

    boost::optional<boost::variant<int, std::string>> f()
    {
        return boost::optional<boost::variant<int, std::string>>{5};
    }
    

    Or as the construction from the contained value type is non-explicit:

    boost::optional<boost::variant<int, std::string>> f()
    {
        return boost::variant<int, std::string>{5};
    }