2

In c++, how is it possible for child class, or friend function to access all possible template types of the parent? How do I modify the code below, so that no matter what the type T is, the friend function and child function will not suffer from type errors? (Currently only the type of int works properly).

// PARENT CLASS:¨

template <class T>
class parent{
public:
    T variable1;

    friend int function1(parent, int a);
};


//CHILD CLASS:

class child : public parent<int> {
public:
    void setvariable(int a){ variable1 = a; };

};


// FRIEND FUNCTION:

int function1(parent<int> k, int a) {
    return k.variable1 +a;
};

So that the following would then compile without errors:

int main() {
    child child1;              //Child
    child child2;

    child1.setvariable(4);
    child2.setvariable(4.4);   //Type error/retyping

    cout << function1(child1.variable1, 4) << endl;     // Function
    cout << function1(child2.variable1, 4.0) << endl;   // Type error

    system("pause");
    return 1;
}
Jonas
  • 6,915
  • 8
  • 35
  • 53
Tony
  • 343
  • 1
  • 6
  • 15
  • Possible duplicate of [declare template friend function of template class](https://stackoverflow.com/questions/18792565/declare-template-friend-function-of-template-class) – AndyG Aug 05 '17 at 20:04
  • 1
    Can you show an example of code you want to have? E.g., a definition of function1? It is, to me, unclear what you are asking for. – Jonas Aug 05 '17 at 20:15
  • @Jonas The definition of the function is on the 2nd to last line ;). – Tony Aug 05 '17 at 20:17
  • Well, obviously it is. But that, presumably, compiles. Do you have an example that you want to have working , but doesn't yet? – Jonas Aug 05 '17 at 20:18
  • @Jonas I have added a simplistic example. – Tony Aug 05 '17 at 20:32
  • 2
    Still the question is unclear. Obviously a float cannot be converted to int... – Andreas H. Aug 05 '17 at 20:53
  • Or do you want "friend int function1(parent, T a);" in class parent? – Andreas H. Aug 05 '17 at 20:54
  • @AndreasH. What I want is for the child and function to work for ANY type, not just int. – Tony Aug 05 '17 at 21:26

3 Answers3

1

This will allow the friend function to access variable1 for all derived types.

//Parent
template <class T>
class parent{
public:
    template<typename U>
    friend U function1(parent<U>& parent, U a);

private:
    T variable1;
};


//Child
class child : public parent<int> {
public:
    void setvariable(int a){ variable1 = a; };
};


//Friend
template<typename U>
U function1(parent<U>& k, U a) {
    return k.variable1 + a;
};
Andreas Loanjoe
  • 2,205
  • 10
  • 26
1

friend function definition can be inside class definition:

template <class T>
class parent{
public:
    T variable1;

    friend T function1(parent k, T a) {
        return k.variable1 + a;
    }
};

That function is not template so allows promotion/conversion.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Very interesting, I though there was fundamentally no difference between writing the function implementation inside the class declaration vs outside. – Tony Aug 06 '17 at 17:47
  • it is the only way to define it for each template without that thefuntion is itself template. – Jarod42 Aug 06 '17 at 18:06
0

I'm not entirely sure what you try to achieve, but I think this could be what you want.

The child class and function1 are now templates and the first parameter of function1 is a reference.

Template parameter is explicitly set when instantiating a child object.

#include <iostream>
using namespace std;
template <class T>
class parent{
public:
    T variable1;

template <class U>
    friend U function1(parent<U>&, U a); // now a template, using U to avoid shadowing 
};

//CHILD CLASS:
template <class T> // now a template
class child : public parent<T> {
public:
    void setvariable(T a){ this->variable1 = a; }; // using 'this' pointer because the function is a template now
};

// FRIEND FUNCTION:
template <class T> // now a template
T function1(parent<T>& k, T a) { // first parameter is a reference, for polymorphism to work
    return k.variable1 +a;
};

int main() {
    child<int> child1;    // T = int
    child<double> child2; // T = double 

    child1.setvariable(4);
    child2.setvariable(4.4); 

    cout << function1(child1, 4) << endl;   // first parameter is child1, and not the member variable
    cout << function1(child2, 4.0) << endl; // first parameter is child2
}
Jonas
  • 6,915
  • 8
  • 35
  • 53