Search code examples
c++boostboost-optional

boost::make_optional with type specification


I'm puzzled about the boost::make_optional() behavior when used with the template specification.

In particular, it's still unclear to me why this:

int pizza = 5;
boost::optional<int> pizza_opt = boost::make_optional<int>(pizza)

throws the compile error cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’; while this:

int foo(int bar)
{ return bar; }

boost::optional<int> pizza_opt = boost::make_optional<int>(foo(pizza))

works fine.

I already know from this that it does not make much sense to use boost::make_optional specifying the type, but I'm reading some code which does use of this structure.

Thank you!


Solution

  • Template parameter of boost::make_optional doesn't define exactly type inside optional.

    This template parameter is responsible for perfect forwarding, here is simple minimal example reproducing issue:

    #include <iostream>
    
    template<typename T>
    void bar(T&& x)
    {
        std::cout << __PRETTY_FUNCTION__ << " " 
            << std::forward<T>(x) << '\n';
    }
    
    int foo(int x)
    {
        return x + 1;
    }
    
    int main()
    {
        int pizza = 5;
        bar(pizza);
        bar<int>(foo(pizza));
        // bar<int>(pizza); // same error
    
        return 0;
    }
    

    Live demo.

    So when deduction is done T is int& for l-values and int for r-values.

    When you pass variable you passing l-value.

    When you specified type you are forcing argument to be int && which do not match to int&.