2

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 ?

bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217

3 Answers3

2

You can write a type trait as

template< class T > struct remove_rvalue_reference       {typedef T type;};
template< class T > struct remove_rvalue_reference <T&&> {typedef T type;};

then

using T = typename remove_rvalue_reference<decltype(t)>::type;

then

auto i = 10;
foo(i);   // T will be int& in the lambda

foo(10);  // T will be int  in the lambda
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
2

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

bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
lubgr
  • 37,368
  • 3
  • 66
  • 117
1

Expanding on lubgr's answer you can encapsulate the conditional type in an alias compatible with C++14 like this:

#include <type_traits>

template <class T>
using decay_rvalue_reference_t = std::conditional_t<
    std::is_rvalue_reference<T>::value,
    std::decay_t<T>::type,
    T>;

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

https://godbolt.org/z/YW88Yf

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • In my production code this is exactly what I did. A nice addition to the answers! – bradgonesurfing Feb 09 '21 at 07:15
  • @bradgonesurfing I originally thought my answer was more useful until I realized the `_t` variants were in fact available in C++14 `` header. Now I think my answer is only marginally useful :P (I managed to get the edit in before the 5 minute window so you can't see my original answer) – Patrick Roberts Feb 09 '21 at 07:16
  • 1
    I still think it is a good idea to factor things like this out because when reading the code later on you see the concept ``decay_rvalue_reference_t`` named rather than the implementation. It's a small thing but it's worth it. – bradgonesurfing Feb 09 '21 at 07:21