Weird Template Friends Question

I'm trying to program a template class that has a template friend function. I managed to get the class to work, but I'm not sure why it works. First, I'll post the one that didn't work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
using namespace std;
template <typename T> class Mock; //Forward declaration...
template <typename T, typename T2>
int somefunction(Mock<T> Param1, T2 Param2);
template <typename T>
class Mock
{
  public:
  Mock() {};
  ~Mock() {};
  T s; //Not used. Just experimenting.
  template <typename T, typename T2>
  friend int somefunction(Mock<T> Param1, T2 Param2);
};

template <typename T, typename T2>
int somefunction(Mock<T> Param1, T2 Param2)
{
  std::cout << "Hello World.\n";
  std::cin.get();
  /*I know, system calls are "evil" but this is just a mock of the real project
  * to demonstrate...what I'm trying to do. 
  */
  return 0;
}

int main()
{
  Mock<int> a;
  double c;
  int d = somefunction(a, c);
  return 0;
}


I'm not sure why that didn't work. But what's more confusing to me, is why this worked :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

using namespace std;

template <typename T> class Mock;
template <typename T, typename T2>
int somefunction( Mock<T> Param1,  T2 Param2);
template <typename T>
class Mock
{
    public:
    Mock() {};
    ~Mock() {};
    T s;
    template <typename T3, typename T2>
    friend int somefunction( Mock<T3> Param1,  T2 Param2);
};

template <typename T3, typename T2>
int somefunction(Mock<T3> Param1, T2 Param2)
{
    std::cout << "Hello World.\n";
    std::cin.get();
    return 0;
}

int main()
{
    Mock<int> a;
    double c;
    int d = somefunction(a, c);
    return 0;
}


Also, switching lines 6 and 7, from typename T to typename T3, still works. I'm very confused and very happy, but I'm not sure if I should be happy. Why does this work, and what's the difference?
Last edited on
> Also, switching lines 6 and 7, from typename T to typename T3, still works.

1
2
3
4
5
6
7
8
9
10
template < typename T > struct A
{
    // template< typename T > friend void foo( A<T> ) ; // *** error
    // the template parameter T in A<T> can't be shadowed

    template< typename X > friend void bar( A<X> ) ; // OK
    // the template parameter X does not shadow anything in A<T>
};

template< typename T > void bar( A<T> ) {} // also ok; no longer within A<T> 

Ah, that makes sense. Originally I was trying to overload the friend template functions with T, which also compiled perfectly, but when I tried to call them, I got errors. Then I tried to specialize them, getting an "Trying to specialize in non-namespace scope" error, then when i tried to specialize in namespace scope and friend that, it didn't exist because the class was never specialized...

Needless to say, templates are my nightmare in C++. And my best friends. I'm very happy to finally have all this stuff working. Thank you.
Topic archived. No new replies allowed.