auto in templates?

I am going through tutorials on c++14 and it is introducing the keyword auto. It says it can be used in templates, but what is the point in this? I though in templates the compiler already determines what type of type of template to create, so what does using the auto keyword do? Why does it make it better?

Also, if someone could please show exactly how the template class should look when using auto in the template class, the tutorials I am following do not show it, and all other code I can find on it, includes other keywords I am not familiar with yet, such as constxpr . If the standard template function is the one I have below, how should it look using auto?

1
2
3
4
5
6
 template <class T>
T GetMax (T a, T b) {
  T result;
  result = (a>b)? a : b;
  return (result);
}
Hi

auto is used for non type template parameters, it's not a replacement for all the template parameters:

https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter

One can have a very simple template with a non type parameter like this:

1
2
3
4
5
template<int n>
struct A 
{ 
double d = 0.0;
};


In it's usage, the following are 2 different types:

1
2
A<1> x;
A<2> y;


We can then do this:

1
2
3
using A<1> = distance_t;
using A<2> = angle_t;
using A<3> = area_t;


So this enables different types for function parameters - we need it need it for function overloading, so the compiler can distinguish the different signatures, where the underlying types are all double:

1
2
bool f(distance_t Mydistance, angle_t; MyAngle);
bool f(distance_t Mydistance, area_t; MyAngle);


This is only a simple example, there are many others.

kmce wrote:
.... includes other keywords I am not familiar with yet, such as constxpr .


constexpr is a relatively simple thing to learn.

If the standard template function is the one I have below, how should it look using auto?


It uses type parameters, so it doesn't need auto.

Good Luck !!
There's no point in using auto in your program.
Consider this (incorrect) function template instead:
1
2
3
4
5
template <typename T, typename U> 
  T get_max(T a, U b)
  {
    return a > b? a: b;
  }

The problem lies in the fact that while the function's return type is T, the type of the expression
a > b? a: b
depends instead on the types of a and b, according to complicated rules. For example, if T is int and U is long long, then the type of a > b? a: b is long long.

As such, get_max(1000, std::numeric_limits<long long>:::max()) will convert a > b? a: b from long long to int, which throws away information:
https://godbolt.org/z/YqYjxq

To solve the problem, we need a way to ensure the return type is appropriate for the types involved. Before C++14, we have to write the return type ourselves. It's not a reasonable solution. Here's how it looks, just for kicks:
1
2
3
4
5
6
7
8
template <typename T, typename U> 
  typename std::remove_reference<
    decltype(std::declval<T&>() > std::declval<U&>()? 
      std::declval<T&>(): std::declval<U&>())>::type 
  get_max(T a, U b)
  {
    return a > b? a: b;
  }
This is totally absurd for the problem it solves.

More simply, we can use trailing return types (which exist for this purpose)
1
2
3
4
5
6
template <typename T, typename U> 
  auto get_max(T a, U b) ->
    typename std::remove_reference<decltype(a > b? a: b)>::type
  {
    return a > b? a: b;
  }


But happily we don't need to bother with this, because, since C++14, we can allow the compiler to figure out the appropriate type on its own:
1
2
3
4
5
template <typename T, typename U> 
  auto get_max(T a, U b)
  {
    return a > b? a: b;
  }
Last edited on
There was a lot in these explanations that I did not understand, so apologies if I completely miss what was being explained, but is it basically auto is being used to determine the return type.
But is it basically auto is being used to determine the return type.

Yes. The return type of the function
1
2
3
4
5
template <typename T, typename U> 
  auto get_max(T a, U b)
  {
    return a > b? a: b;
  }

Is the type of the expression a > b? a: b. This type is not necessarily T or U. We chose not to write out this type by hand, since it's complicated, and instead used auto to have the compiler figure out the correct return type on its own.
Last edited on
Topic archived. No new replies allowed.