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!
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;
}
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&
.