why overloading isn't happened?

From: 胡岳偉(Yueh-Wei Hu) (ywhu_at_iii.org.tw)
Date: 05/21/04


Date: 21 May 2004 10:52:40 -0700

Hi all,

I have 2 questions about template function as friends in template
classes. I don't know why, and hope someone could help me.

==============================================================
Question 1:
==============================================================

Compile the following codes, and run it.
The program will print

"T<a, b>"

on the screen.

However, I consider that "T<a, 3>" should be displayed.

Why this program print "T<a, b>"?

My building environment is:

1) gcc-3.3
2) linux kernel 2.6.6

==============================================================

#include <iostream>

template<int a, int b>
class T;

template<int a, int b>
void func(T<a, b> const * const t)
{
  t->c = 3;
  std::cerr << "T<a, b>" << std::endl;
}

template<int a, int b>
class T
{
private:
  
  int c;

  friend void func<a, b>(T<a, b> const * const t);
  friend void func<a>(T<a, 3> const * const t);
  
public:
  
  void ttt() const;
};

template<int a>
void
func(T<a, 3> const * const t)
{
  t->c = 2;
  std::cerr << "T<a, 3>" << std::endl;
}

template<int a, int b>
void
T<a, b>::ttt() const
{
  func(this);
}

int
main()
{
  T<2, 3> t;
  
  t.ttt();
  
  return 0;
}

=============================================================
Question 2:
=============================================================

I add another function template:

friend void func<b>(T<3, b> const * const t);

and define it, too.

However, when I compile this program, gcc shows the following error
message:

eee.cpp: In instantiation of `T<2, 3>':
eee.cpp:50: instantiated from here
eee.cpp:19: error: ambiguous template specialization `func<3>' for
`void
   func(const T<3, 3>*)'

What does the 'ambiguous template specialization' indicate?
I can't figure it out.

Thank you for your help.

=============================================================

#include <iostream>

template<int a, int b>
class T;

template<int a, int b>
void func(T<a, b> const * const t)
{
  t->c = 3;
  std::cerr << "T<a, b>" << std::endl;
}

template<int a, int b>
class T
{
private:
  
  friend void func<a, b>(T<a, b> const * const t);
  //friend void func<a>(T<a, 3> const * const t);
  friend void func<b>(T<3, b> const * const t); <-- add this line -->
  
public:
  
  void ttt() const;
};

template<int a>
void
func(T<a, 3> const * const t)
{
  t->c = 2;
  std::cerr << "T<a, 3>" << std::endl;
}

template<int b> <-- add definition -->
void
func(T<3, b> const * const t)
{
  t->c = 1;
  std::cerr << "T<3, b>" << std::endl;
}

template<int a, int b>
void
T<a, b>::ttt() const
{
  func(this);
}

int
main()
{
  T<2, 3> t;
  
  t.ttt();

  return 0;
}

==============================================================