Understanding decltype(auto) difference in case of template vs auto functions

Viewed 269

I need help understanding why the return type of updateElementUsingTemplate differ from updateElementUsingAuto in the below provided code.

#include <iostream>
#include <array>
#include <vector>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;

template<typename Container, typename Index>
decltype(auto) updateElementUsingTemplate(Container&& container, Index index)
{    
    std::cout << "Template Return Type : "<<
    type_id_with_cvr<decltype( container[index] )>().pretty_name() << '\n';
    return container[index];
}

decltype(auto) updateElementUsingAuto(auto&& container, size_t index)
{
    std::cout << "Auto Return Type : "<<
    type_id_with_cvr<decltype( container[index] )>().pretty_name() << '\n';
    return container[index];
}

int main() {
    std::array<int,2> arr= {1,2};
    updateElementUsingTemplate( arr, 1 ) = 12;
    updateElementUsingAuto( arr, 1 );// = 12;
    //Generates compiler error if uncommented: lvalue required as left operand of assignment.
    //Why is type being returned "int" in above statement?
    std::cout << "Auto Returned Type : "<< 
type_id_with_cvr<decltype( updateElementUsingAuto(arr,1) )>().pretty_name() << '\n';
    std::cout << "Template Returned Type : "<<
type_id_with_cvr<decltype( updateElementUsingTemplate(arr,1) )>().pretty_name() << '\n';
    return 0;
}

Actual Result:
Template Return Type : int&
Auto Return Type : int&
Auto Returned Type : int
Template Returned Type : int&

Expected Result :
Template Return Type : int&
Auto Return Type : int&
Auto Returned Type : int&
Template Returned Type : int&

I was expecting updateElementUsingAuto and updateElementUsingTemplate both to return int&, where as actual results returned are int and int& respectively.
Why is there difference in return type of both functions?

Your help will be highly appreciated.

Edit 1: As mentioned by @cpplearner, this issue seems to be a gcc bug.
If someone still wants to use the syntax, you can do so by using trailing type syntax :
decltype(auto) updateElementUsingAuto(auto&& container, size_t index) -> decltype( container[index] ){ ... }

0 Answers
Related