0

I need to define a friend function for the templated class. The function has return type that is a member type of the class. Now, I can not declare it beforehand, since the the return type is not known at the time. Something like this

template<class T> class A; 

//This doesn't work: error: need ‘typename’ before...  
template<class T> A<T>::member_type fcn(A<T>::member_type);

//This doesn't work: error: template declaration of ‘typename...
template<class T> typename A<T>::member_type fcn(A<T>::member_type);

template<class T>
class A{
public:
  typedef int member_type;
  friend member_type fcn<T>(member_type);
};

How do I do this?

user1672572
  • 321
  • 2
  • 9

4 Answers4

1

I managed to compile that code on g++ using :

template<class T> typename A<T>::member_type fcn(typename A<T>::member_type);

(Thus a second 'typename' was required)

gogoprog
  • 613
  • 4
  • 7
1

You need to say typename also in the argument:

template <class T>
typename A<T>::member_type fcn(typename A<T>::member_type);
//                             ^^^^^^^^

Otherwise there's no problem with your code, as long as all the template definitions appear before the function template is first instantiated.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

It seems that in your particular example nothing in fcn function actually depends on class A. It doesn't even need to access any of the A's methods/fields, neither public nor protected/private. So it doesn't make sense. It would have made some sense otherwise, but at any rate it seems like it is worth re-thinking your problem and come up with a cleaner solution that does not need a hack like that. If, after a deep thought, you still believe you need it, you can do something like this:

#include <cstdio>

template<typename T> typename T::member_type fcn(const T & v) {
    return v.value_;
}

template<class T>
class A {
  public:
    typedef T member_type;

    friend member_type fcn< A<T> >(const A<T> &);

    A() : value_(1986) {}

  private:
    T value_;
};

int main()
{
    A<int> a;
    printf("The value is: %d\n", fcn(a));
}

Notable thing in the above example is that you need to de-couple a cross dependency and make your free-function not depend on a declaration of class A. If you still feel like you need that coupling, the following code works, too:

#include <cstdio>

template <typename T>
class A;

template <typename T> typename A<T>::member_type fcn(const A<T> & v) {
    return v.value_;
}

template <typename T>
class A {
  public:
    typedef int member_type;

    friend member_type fcn<T>(const A<T> &);

    A() : value_(1986) {}

  private:
    member_type value_;
};

int main()
{
    A<void> a;
    printf("The value is: %d\n", fcn(a));
}

Hope it helps. Good Luck!

1

This may by now be redundant with someone else's answer, but here's a complete, testable solution. The final function definition is a template specialization of fcn, which will produce a compiler error indicating that A<double>::x is not accessible from fcn<int>, but A<int>::x is accessible.

template<class T> class A; 

template <typename U>
typename A<U>::member_type fcn(typename A<U>::member_type);

template<class T>
class A {
    int x;
  public:
    typedef int member_type;
    friend typename A<T>::member_type fcn<T>(typename A<T>::member_type);
};

template<>
int fcn<int>(int x)
{
    A<int> i;
    A<double> d;
    i.x = 0;  // permitted
    d.x = 0;  // forbidden
    return 0;
}
Quuxplusone
  • 23,928
  • 8
  • 94
  • 159