Daniel Lee
Daniel Lee

Reputation: 215

template overloading resolution rules

Just can't understand what's going on. Is there anyone who can explain these clearly? If so, please give me some clues or keywords to search.

template <typename T1, typename T2>
auto max (T1 a, T2 b) {
  std::cout << "1" << std::endl;
  return a > b ? a : b;
}

template <typename RT, typename T1, typename T2>
RT max (T1 a, T2 b) {
  std::cout << "2" << std::endl;
  return a > b ? a : b;
}

void func() {
  auto a = max(4, 7.2); // 1 ? 
  auto b = max<long double>(7.2, 4); // 2 ?
  auto c = max<int>(3.4, 2); // 2 ?
  auto e = max<double, int>(3.4, 2); // 1 ?
}

If 2nd max function is not defined, every max call works just fine. On what ground 2nd max is called. What's the rule for it?

Upvotes: 2

Views: 64

Answers (2)

Gem Taylor
Gem Taylor

Reputation: 5613

If you don't specify a template type, the second form is never used, because RT cannot be deduced, and must be specified.

If you do specify a type, and it is different to T1 deduced from the argument then the second form is used.

Note that the first form is actually C++14, not C++11. In C++11 you have to specify the return type one way or another.

The second form is C++11, and might be provided in C++14 for backward compatibility. Also in principle the second form lets you control the widening, but in practice I'm not sure what the second form gets you, as ?: has to resolve to a single size type. [This answers your supplementary question I think]

For example if the two types were signed and unsigned and the return type was double (but you would get a warning), the ?: result would be probably unsigned (or an error), then cast to double, which is unhelpful. Ideally you need a third version to handle signed/unsigned mismatch anyway, if you care - this is a whole can of special case worms to resolve cleanly.

If it was written long-hand with 2 return statements then it would correctly widen both halves. Better yet, if the casts were performed before the comparison...

Upvotes: 3

Thomas Sablik
Thomas Sablik

Reputation: 16455

max(4, 7.2) generates a function from first template because two parameters <int, double> are known.
max<long double>(7.2, 4) generates a function from second template because three parameters (long double, double, int) are known.
max<int>(4, 7.2) is the same as before.
max<double, int>(3.4, 2) generates a function from first template because the two given template parameters fit to the given values. The two parameters are <double, int>

The compiler tries to deduce the types from function call, if no template parameters are given.

Upvotes: 1

Related Questions