2

1.. I'm testing following code which uses template
Source code is originated from this learncpp tutorial
https://www.learncpp.com/cpp-tutorial/132-function-template-instances/

#include <iostream>
#include <cstring>
#include <typeinfo>
using namespace std;

// ======================================================================
template <typename T>
const T& max(const T& x,const T& y)
{
  return (x>y)?x:y;
}

// ======================================================================
class Cents
{
private:
  int m_cents;
public:
  Cents(int cents):m_cents(cents)
  {
  }

  friend bool operator>(const Cents &c1,const Cents &c2)
  {
    return (c1.m_cents>c2.m_cents);
  }

  int get_val()
  {
    m_cents;
  }
};

// ======================================================================
int main()
{
  Cents nickle(5);
  Cents dime(10);

  Cents bigger=max(nickle,dime);
  // std::cout<<"bigger: "<<bigger.get_val()<<std::endl;
  // bigger: 1471225424

  return 0;
}

And I get this error

error: call of overloaded ‘max(Cents&, Cents&)’ is ambiguous
   Cents bigger=max(nickle,dime);

What's wrong with the code?

2.. And how can I print result?
For example, I tried std::cout<<"bigger: "<<bigger<<std::endl;
But I ran into following error which says there is no overloaded operator << for bigger(Cent type object)

error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
   std::cout<<"bigger: "<<bigger<<std::endl;
error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘Cents’)
   std::cout<<"bigger: "<<bigger<<std::endl;
YoungMin Park
  • 1,101
  • 1
  • 10
  • 18
  • Concerning `std::cout << "bigger: " << bigger << std::endl`: I don't see you define a suitable `operator <<` that could take an object of type `Cents` anywhere, so what exactly do you expect this should do? – Michael Kenzel Apr 16 '19 at 01:34
  • @MichaelKenzel I edited code to specify what I would like to do with "returned bigger object". – YoungMin Park Apr 16 '19 at 01:40

1 Answers1

2

The namespace std also contains a function template named max which has a signature basically identical to your max function template. While you did not explicitly include the header in which std::max is officially defined (<algorithm>), an implementation may include any library header from any other library header [res.on.headers]/1, so it is perfectly legal (and something that code using the standard library must expect to deal with) that std::max ends up being declared in namespace std in your case. The

using namespace std;

directive at the top will then introduce the std::max function template into the global namespace. Thus, at any point after this using directive, unqualified name lookup will find two function templates named max in the global namespace that have identical signatures and, thus, your call to max will be ambiguous (it cannot be decided which function should be called as they're both equally valid choices). To fix the issue, get rid of the using namespace std; (recommended) or explicitly identify the target of your max function call via qualified name, e.g.:

Cents bigger = ::max(nickle, dime);
Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
  • Thanks. That solved error with max(). And could you advise how to print returned object from max()? I tried to create public get_val() which returns m_cents. So, as soon as I got bigger object from max(), I tried bigger.get_val(). But value looked like garbage value like 1471225424 – YoungMin Park Apr 16 '19 at 01:37