Search code examples
c++c++-conceptstype-deductiontype-declaration

What should be deduced by decltype(auto) for automatically type deduced argument?


I thought that these two functions should have had the same return type:

template<class T>
decltype(auto) f(T&& a){return a;}
decltype(auto) g(auto&& a){return a;}

Nevertheless, using gcc7, these functions verify:

int i;
static_assert(std::is_same< decltype(f(i)), int& >::value);
static_assert(std::is_same< decltype(g(i)), int  >::value);

Why are the return types of g and f different?


Solution

  • The definition

    decltype(auto) g(auto&& a){return a;}
    

    is not Standard C++. It might be part of the upcoming Concepts Lite feature. g++ provides the syntax as an extension (even without -fconcepts).

    Compiling with -Wpedantic in fact produces a warning:

    warning: ISO C++ forbids use of 'auto' in parameter declaration [-Wpedantic]
     decltype(auto) g(auto&& a){return a;}
                      ^~~~
    

    Since the behavior is not standardized yet, it is unclear whether your static_assert should be truthy or not - intuitively I agree that decltype(g(i)) should be int& though. This could simply be a "defect" in how g++ implements non-member function auto parameters.


    The closest Standard-compliant thing to what you're trying to do is a lambda expression:

    auto z = [](auto&& a) -> decltype(auto) { return a; };
    

    In the case of z, the static_assert works as expected:

    static_assert(std::is_same< decltype(z(i)), int&  >::value);