3

The following code throws compiler error when I compile it.

template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}

// maximum of two C-strings (call-by-value)
inline char const* max (char const* a, char const* b)
{
    return strcmp(a,b) < 0 ? b : a;
}

// maximum of three values of any type (call-by-reference)
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max (max(a,b), c); 
}

int main ()
{
    ::max(7, 42, 68);  
}

On compilation I get the error :

error: call of overloaded 'max(const int&, const int&)' is ambiguous

note: candidates are:

note: const T& max(const T&, const T&) [with T =int]

note: const char* max(const char*, const char*)

How does max(const char*, const char*) becomes a near match for max(const int&, const int &) when we have the template method that matches the call?

sajas
  • 1,599
  • 1
  • 17
  • 39
  • try this `const char* x = 42;` and that should anser ur question – Kal Oct 07 '13 at 02:32
  • 2
    What compiler? It works fine for me: http://coliru.stacked-crooked.com/a/d125ccc03238992e – aschepler Oct 07 '13 at 02:33
  • Your function returns a const-reference, and you're passing a tempval. technically, the template doesn't even fit. Does it change if you remove the `const&` from the template return type ? – WhozCraig Oct 07 '13 at 02:33
  • @WhozCraig the template fits, why wouldn't it? It's just UB to use the return value after that outermost `max` returns – Kal Oct 07 '13 at 02:34
  • @Kal ok, brutal, but true. i stand corrected. I'm now curious to see what toolchain this is. – WhozCraig Oct 07 '13 at 02:35
  • @WhozCraig: What's a temporary here? – aschepler Oct 07 '13 at 02:35
  • @aschepler the immediate's (7, 42, and 68) passed in for the parameters `T const& a` and `T const& b`. – WhozCraig Oct 07 '13 at 02:37
  • I am using mingw32-g++.exe GNU GCC Compiler with codeBlocks – sajas Oct 07 '13 at 02:38
  • Like others, works with clang 3.4 (UB and all). Just tried it with gcc 4.2 on my Mac, and it compiled there as well. – WhozCraig Oct 07 '13 at 02:43
  • @WhozCraig: Okay, but they last for the entire statement in `main`. `int n = ::max(7,42,68);` would be just fine too. – aschepler Oct 07 '13 at 02:52
  • @aschepler correct. `const int& n` would not, but yours would. I'm really wondering what version of gcc is being used now, because mine eats this without issue. – WhozCraig Oct 07 '13 at 02:54
  • How do I find the version of the mingw exe? In the folder I found mingw32-gcc-4.7.1. It was in the CodeBlocks folder – sajas Oct 07 '13 at 03:06
  • @sajas thats all we needed. its v4.7.1. I tried a variadic approach while keeping the references, and was loathed to discover it actually didn't work on my chain (compiled, but produced garbage output). The sample I tried [can be found here on ideone.com](http://ideone.com/ZPeZLB). I'm curious if it works with gcc 4.7.1 if you have the spare time. – WhozCraig Oct 07 '13 at 03:08
  • I tried the code that you gave and it worked in mine. It gave 100. – sajas Oct 07 '13 at 03:13
  • @sajas That *is* interesting. Now i'm curious to know if your trio still tries to pick your `const char*` with your override present and the variadic present as well. i honestly don't see how it could, but none-the-less am wondering. – WhozCraig Oct 07 '13 at 04:17
  • 1
    @sajas [Check that ideone.com post](http://ideone.com/ZPeZLB) one more time. I'm curious if that does what you're looking for. It may seem a little odd, but providing a variadic pointer override seems to work. Wish you the best of luck. Interesting question. Btw, check your code. I don't suppose you have a `using namespace std;` at the top of your file? – WhozCraig Oct 07 '13 at 04:39
  • @WhozCraig Sorry, I had the using namespace directive. Sorry about your time. And Thanks a lot for you help. – sajas Oct 07 '13 at 13:38

1 Answers1

1

I bet you have using namespace std in your code. Remove it and you'll be fine.

Compare: http://ideone.com/Csq8SV and http://ideone.com/IQAoI6

If you strictly need namespace std to be used, you can force root namespace call (the way do it in main()):

template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return ::max(::max(a,b), c); 
}
Alexey Biryukov
  • 649
  • 8
  • 15