Search code examples
c++lambdac++14boost-optional

How to decay rvalues reference type whilst preserving lvalue references in C++14?


I have the following C++14 lambda

https://godbolt.org/z/aexxTY

#include <boost/optional.hpp>


int main(){
    auto foo = [](auto && t) 
    {
        using T = decltype(t);
        return boost::optional<T>(std::forward<T>(t));
    };

    // This is fine because i is lvalue
    auto i = 10;
    foo(i);

    // This fails because i is rvalue
    foo(10);
}

First note that boost::optional can contain lvalue references but not rvalue references.

Is it possible with the above generic lambda to handle the rvalue as a copy. What I'd like is something clever like

using T = std::decay_if_rvalue<decltype(t)>::type

Is there something out of the box that does this ?


Solution

  • You could use std::is_rvalue_reference together with std::conditional, both from the <type_traits> header.

    auto foo = [](auto && t) 
    {
        using Orig = decltype(t);
        using T = std::conditional_t<std::is_rvalue_reference<Orig>::value,
                std::decay_t<Orig>, Orig>;
        return boost::optional<T>(std::forward<T>(t));
    };
    

    https://godbolt.org/z/WdTdco