6

Using GCC 4.8.4 with g++ --std=c++11 main.cpp outputs the following error

error: unable to deduce ‘auto’ from ‘max<int>’
auto stdMaxInt = std::max<int>;

for this code

#include <algorithm>

template<class T>
const T& myMax(const T& a, const T& b)
{
    return (a < b) ? b : a;
}

int main()
{
    auto myMaxInt = myMax<int>;
    myMaxInt(1, 2);

    auto stdMaxInt = std::max<int>;
    stdMaxInt(1, 2);
}

Why does it work with myMax but not with std::max? And can we make it work with std::max?

bogdan
  • 9,229
  • 2
  • 33
  • 48
Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134
  • I don't know the precise answer to your question but I think it has to do with the fact that std::max is overloaded to be a const expression when the operands qualify. Your version has no such overloads, and so there's no ambiguity. The easiest way to tackle this problem without immersing yourself in the details might be to simply use `myMax` (or a lambda, e.g.) for this kind of use scenario, but simply make it call `std::max` in its implementation. –  Nov 14 '15 at 07:22
  • @Ike `std::max` is overloaded with another signature to take a third parameter, a comparison object. The compiler doesn't know which overload is intended. – Weak to Enuma Elish Nov 14 '15 at 07:28
  • `decltype(auto) stdMaxInt = ...` with c++14 shows clear info – billz Nov 14 '15 at 07:30
  • Oh I see, I missed that overload as well. Now I'm curious about the constexpr overload -- if that constitutes an ambiguity of sorts or not, and how that gets resolved in the capture to auto. –  Nov 14 '15 at 07:30
  • 1
    @Ike It looks like after c++14 came around, all the versions became `constexpr`, so there really isn't an overload for it. – Weak to Enuma Elish Nov 14 '15 at 07:36
  • Ah I see -- a bit behind on the times. –  Nov 14 '15 at 07:37
  • why are you helping the compiler? what's wrong with `std::max(1,2)`? – TemplateRex Nov 14 '15 at 08:32
  • Nothing is wrong with `std::max(1,2)`. I am just experimenting to improve my understanding of the language. – Tobias Hermann Nov 14 '15 at 08:38

2 Answers2

5

It's because std::max is an overloaded function, so it doesn't know which overload you want to create a pointer to. You can use static_cast to select the overload you want.

auto stdMaxInt = static_cast<const int&(*)(const int&, const int&)>(std::max<int>);
Weak to Enuma Elish
  • 4,622
  • 3
  • 24
  • 36
2

The static_cast answer by @JamesRoot works, but for my taste, I'd prefer a lambda:

auto stdMaxInt = [](int const& L, int const& R) -> int const& { return std::max(L, R); };

This might have the advantage of better inline-ability when passed to algorithms (untested).

TemplateRex
  • 69,038
  • 19
  • 164
  • 304