Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abbreviated function template vs. function template with forwarding reference param

What are the differences between function templates with forwarding reference parameters

template<typename T>
void Universal_func(T && a)
{
}

and abbreviated function templates?

void auto_fun(auto && a)
{
}

Can I replace Universal_func with auto_fun? Is Universal_func a of auto_fun or are they equal?

I have tested the below program. It seems that both are the same.

template<typename T>
void Universal_func(T && a)
{
}

void auto_fun(auto && a)
{
}

int main()
{
  int i;   
  const int const_i = 0; 
  const int const_ref =const_i; 
  //forwarding reference template function example  
  Universal_func(1); //call void Universal_func<int>(int&&)
  Universal_func(i);//call void Universal_func<int&>(int&):
  Universal_func(const_i); //call void Universal_func<int const&>(int const&)
  Universal_func(const_ref);//call void Universal_func<int const&>(int const&)

  //auto calls  
  auto_fun(1); //call void auto_fun<int>(int&&)
  auto_fun(i);//call void auto_fun<int&>(int&):
  auto_fun(const_i); //call void auto_fun<int const&>(int const&)
  auto_fun(const_ref);//call void auto_fun<int const&>(int const&)
  return 0;
}

Universal_func and auto_fun deduced and expanded to similar functions.

void Universal_func<int>(int&&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret
void Universal_func<int&>(int&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret
void Universal_func<int const&>(int const&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret
void auto_fun<int>(int&&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret
void auto_fun<int&>(int&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret
void auto_fun<int const&>(int const&):
        pushq   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)
        nop
        popq    %rbp
        ret

Are there any differences? What does the standard say?

like image 755
Ajay yadav Avatar asked Jan 21 '16 08:01

Ajay yadav


1 Answers

auto in function parameters is not part of standard C++ yet, but some recent versions of GCC allow this as an extension as part of their support for the Concepts TS.

The Concepts TS refers to this construct as an abbreviated function template (although it used to be known as a generic function, which I guess was too generic a term). The rules are perhaps too large to dump into this answer, but have a look in [dcl.fct]/16-19 in this draft for all the gory details.

Paragraph 16 provides a decent overview:

An abbreviated function template is a function declaration whose parameter-type-list includes one or more placeholders (7.1.6.4). An abbreviated function template is equivalent to a function template (14.6.6) whose template-parameter-list includes one invented template-parameter for each occurrence of a placeholder in the parameter-declaration-clause, in order of appearance, according to the rules below. [ Note: Template parameters are also invented to deduce the type of a variable or the return type of a function when the declared type contains placeholders (7.1.6.4.1). — end note ]

By the rules set forth in that draft, your two definitions are functionally equivalent.

We take the function with a placeholder parameter:

void auto_fun(auto && a)
{
}

And invent a template parameter to replace it with:

template <typename T>
void auto_fun (T && a)
{
}

As you can see, this has the same signature as your function without placeholders:

template <typename T>
void Universal_func(T && a)
{
}
like image 150
TartanLlama Avatar answered Sep 28 '22 08:09

TartanLlama