Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an `std::forward` alias - unexpected results

I created an std::forward alias that should behave exactly as std::forward.

template<class T> 
constexpr decltype(auto) fwd(T mValue) noexcept
{ 
    return std::forward<T>(mValue); 
}

I then replaced all occurrences of std::forward<...> with fwd<...> in my codebase.

Compiled all the projects with g++ 4.9 - all tests passed, everything worked properly.

Then I tried compiling with clang++ 3.5. Some tests seemed to randomly fail, and the reason was fwd<...>. Replacing it with std::forward<...> again fixed the failing tests.

I tried writing fwd<...> with the trailing return type syntax, as I thought decltype(auto) wasn't working:

template<class T> 
constexpr auto fwd(T mValue) noexcept -> decltype(std::forward<T>(mValue)) 
{ 
    return std::forward<T>(mValue); 
}

Same results: g++ works, clang++ doesn't.

I then looked up the signature of std::forward on cppreference, and implemented my alias like this:

template<class T> 
constexpr T&& fwd(std::remove_reference_t<T>& t) { return std::forward<T>(t); }

template<class T> 
constexpr T&& fwd(std::remove_reference_t<T>&& t) { return std::forward<T>(t); }

This works (all tests pass) both on g++ and clang++.

Why isn't the decltype(auto) version working? Shouldn't it return the exact same return type as std::forward?

like image 219
Vittorio Romeo Avatar asked Oct 31 '22 16:10

Vittorio Romeo


1 Answers

You forgot to declare mValue as a move reference

template <typename T>
constexpr decltype(auto) fwd(std::remove_reference_t<T> &&mValue)
{
    return std::forward<T>(mValue);
}
template <typename T>
constexpr decltype(auto) fwd(std::remove_reference_t<T> &mValue)
{
    return std::forward<T>(mValue);
}
like image 70
programmerjake Avatar answered Nov 15 '22 04:11

programmerjake