Template class error


i'take error line 31,32,33,34.i didn't solve it.thank you
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <cstdlib>
#include <iostream>

using namespace std;
//////////////////////////////////////////////////////
template < class T >
class Frac
{
      private:
              T share;
              T denominator;
              char karakter;
      public:
             Frac(): share(0.0),denominator(0.0)
             { }
             
             Frac(T p,T pd): share(p),denominator(pd)
             { }
             
             void get_frac()
             {
                  cout << "Enter share: "; cin >> share;
                  cout << "Enter denominator:"; cin >> denominator;
             }
             
             void show_frac()
             {
                  cout << share << "/" << denominator << endl;
             }
             
         friend Frac<T> operator + (Frac<T> k1,Frac<T> k2);
         friend Frac<T> operator - (Frac<T> k1,Frac<T> k2);
         friend Frac<T> operator * (Frac<T> k1,Frac<T> k2);
         friend Frac<T> operator / (Frac<T> k1,Frac<T> k2);
                           
};

///////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator + (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share + k2.share;
     T pd = k1.denominator + k2.denominator;
     
     return Frac<T>(p,pd);
}
///////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator - (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share - k2.share;
     T pd = k1.denominator - k2.denominator;
     
     return Frac<T>(p,pd);
}
///////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator * (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share * k2.share;
     T pd = k1.denominator * k2.denominator;
     
     return Frac<T>(p,pd);
}
////////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator / (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share / k2.share;
     T pd = k1.denominator / k2.denominator;
     
     return Frac<T>(p,pd);
}
//////////////////////////////////////////////////////////////////////////

int main(int argc, char *argv[])
{
    Frac<double> f1;
    Frac<double> f2;
    Frac<double> result;
    
    f1.get_frac();
    f2.get_frac();
    
    
    result = f1 + f2;
    
    result.show_frac();
    
   

    
    system("PAUSE");
    return EXIT_SUCCESS;
}

[Warning] (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

[Warning] friend declaration `Frac<T> operator-(Frac<T>, Frac<T>)' declares a non-template function
help
((I'm never sure about the legal/copyright issues of copying and pasting extracts from books - but this is taken from C++ Templates the Complete guide by david Vandevoorde and Nicolai Josuttis and published by Addison Wesley))

Should be of help.

8.4 Friends
The basic idea of friend declarations is a simple one: Identify classes or functions that have a privileged connection with the class in which the friend declaration appears. Matters are somewhat complicated, however, by two facts:

A friend declaration may be the only declaration of an entity.

A friend function declaration can be a definition.

Friend class declarations cannot be definitions and therefore are rarely problematic. In the context of templates, the only new facet of friend class declarations is the ability to name a particular instance of a class template as a friend:

1
2
3
4
5
6
7
8
template <typename T> 
class Node; 

template <typename T> 
class Tree { 
    friend class Node<T>; 
    … 
}; 

Note that the class template must be visible at the point where one of its instances is made a friend of a class or class template. With an ordinary class, there is no such requirement:

1
2
3
4
5
template <typename T> 
class Tree { 
    friend class Factory;        // OK, even if first declaration of Factory 
    friend class class Node<T>;  // ERROR if Node isn't visible 
}; 

Section 9.2.2 on page 125 has more to say about this.

8.4.1 Friend Functions
An instance of a function template can be made a friend by making sure the name of the friend function is followed by angle brackets. The angle brackets can contain the template arguments, but if the arguments can be deduced, the angle brackets can be left empty:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename T1, typename T2> 
void combine(T1, T2); 

class Mixer { 
    friend void combine<>(int&, int&); 
                        // OK: T1 = int&, T2 = int& 
    friend void combine<int, int>(int, int); 
                        // OK: T1 = int, T2 = int 
    friend void combine<char>(char, int); 
                        // OK: T1 = char T2 = int 
    friend void combine<char>(char&, int); 
                        // ERROR: doesn't match combine() template 
    friend void combine<>(long, long) { … } 
                        // ERROR: definition not allowed! 
}; 

Note that we cannot define a template instance (at most, we can define a specialization), and hence a friend declaration that names an instance cannot be a definition.

If the name is not followed by angle brackets, there are two possibilities:

If the name isn't qualified (in other words, it doesn't contain a double colon), it never refers to a template instance. If no matching nontemplate function is visible at the point of the friend declaration, the friend declaration is the first declaration of that function. The declaration could also be a definition.

If the name is qualified (it contains ::), the name must refer to a previously declared function or function template. A matching function is preferred over a matching function template. However, such a friend declaration cannot be a definition.

An example may help clarify the various possibilities:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void multiply (void*);   // ordinary function 

template <typename T> 
void multiply(T);        // function template 

class Comrades { 
    friend multiply(int) {} 
                         // defines a new function ::multiply(int) 

    friend ::multiply(void*); 
                         // refers to the ordinary function above; 
                         // not to the multiply<void*> instance 

    friend ::multiply(int); 
                         // refers to an instance of the template 

    friend ::multiply<double*>(double*); 
                         // qualified names can also have angle brackets 
                         // but a template must be visible. 

    friend ::error() {} 
                         // ERROR: a qualified friend cannot be a definition 
}; 

In our previous examples, we declared the friend functions in an ordinary class. The same rules apply when we declare them in class templates, but the template parameters may participate in identifying the function that is to be a friend:

1
2
3
4
5
6
7
8
9
10
11
template <typename T> 
class Node { 
    Node<T>* allocate(); 
    … 
}; 

template <typename T> 
class List { 
    friend Node<T>* Node<T>::allocate(); 
    … 
}; 

However, an interesting effect occurs when a friend function is defined in a class template because anything that is only declared in a template isn't a concrete entity until the template is instantiated. Consider the following example:

1
2
3
4
5
6
template <typename T> 
class Creator { 
    friend void appear() {  // a new function ::appear(), but it doesn't // exist until Creator is instantiated 
    } 
}; 


1
2
Creator<void> miracle;  // ::appear() is created at this point 
Creator<double> oops;   // ERROR: ::appear() is created a second time!  

In this example, two different instantiations create two identical definitions—a direct violation of the ODR (see Appendix A).

We must therefore make sure the template parameters of the class template appear in the type of any friend function defined in that template (unless we want to prevent more than one instantiation of a class template in a particular file, but this is rather unlikely). Let's apply this to a variation of our previous example:

1
2
3
4
5
6
template <typename T> 
class Creator { 
    friend void feed(Creator<T>*){  // every T generates a different // function ::feed() 
    } 
}; 

1
2
Creator<void> one;     // generates ::feed(Creator<void>*) 
Creator<double> two;   // generates ::feed(Creator<double>*)  

In this example, every instantiation of Creator generates a different function. Note that even though these functions are generated as part of the instantiation of a template, the functions themselves are ordinary functions, not instances of a template.

Also note that because the body of these functions is defined inside a class definition, they are implicitly inline. Hence, it is not an error for the same function to be generated in two different translation units. Section 9.2.2 on page 125 and Section 11.7 on page 174 have more to say about this topic.

8.4.2 Friend Templates
Usually when declaring a friend that is an instance of a function or a class template, we can express exactly which entity is to be the friend. Sometimes it is nonetheless useful to express that all instances of a template are friends of a class. This requires a so-called friend template. For example:

1
2
3
4
5
6
7
8
9
10
11
class Manager { 
    template<typename T> 
        friend class Task; 
    template<typename T> 
        friend void Schedule<T>::dispatch(Task<T>*); 
    template<typename T> 
        friend int ticket() { 
            return ++Manager::counter; 
        } 
    static int counter; 
}; 

Just as with ordinary friend declarations a friend template can be a definition only if it names an unqualified function name that is not followed by angle brackets.

A friend template can declare only primary templates and members of primary templates. Any partial specializations and explicit specializations associated with a primary template are automatically considered friends too.

Last edited on
thank you.That's very great info.i understand.Somebody helped me.he suggestion to me :
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <cstdlib>
#include <iostream>

using namespace std;
//////////////////////////////////////////////////////
template < class T >
class Frac
{
      public:
              T share;
              T denominator;
              char karakter;
      public:
             Frac(): share(0.0),denominator(0.0)
             { }
             
             Frac(T p,T pd): share(p),denominator(pd)
             { }
             
             void get_frac()
             {
                  cout << "Enter share: "; cin >> share;
                  cout << "Enter denominator:"; cin >> denominator;
             }
             
             void show_frac()
             {
                  cout << share << "/" << denominator << endl;
             }
        template <class TT>    
         friend Frac<T> operator + (Frac<T> k1,Frac<T> k2);
         template <class TT>
         friend Frac<T> operator - (Frac<T> k1,Frac<T> k2);
         template <class TT>
         friend Frac<T> operator * (Frac<T> k1,Frac<T> k2);
         template <class TT>
         friend Frac<T> operator / (Frac<T> k1,Frac<T> k2);
                           
};

///////////////////////////////////////////////////////////////////////

template <class T>
Frac<T> operator + (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share + k2.share;
     T pd = k1.denominator + k2.denominator;
     
     return Frac<T>(p,pd);
}

///////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator - (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share - k2.share;
     T pd = k1.denominator - k2.denominator;
     
     return Frac<T>(p,pd);
}
///////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator * (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share * k2.share;
     T pd = k1.denominator * k2.denominator;
     
     return Frac<T>(p,pd);
}
////////////////////////////////////////////////////////////////////////
template <class T>
Frac<T> operator / (Frac<T> k1,Frac<T> k2)
{
     T p = k1.share / k2.share;
     T pd = k1.denominator / k2.denominator;
     
     return Frac<T>(p,pd);
}
//////////////////////////////////////////////////////////////////////////

int main(int argc, char *argv[])
{
    Frac<double> f1;
    Frac<double> f2;
    Frac<double> result;
    
    f1.get_frac();
    f2.get_frac();
    
    
    result = f1 + f2;
    
    result.show_frac();
    
   

    
    system("PAUSE");
    return EXIT_SUCCESS;
}
http://www.cplusplus.com/forum/beginner/1/

If You Can't Get An Answer
If you can't get an answer, please don't take it personally that we don't feel we can help you. Sometimes the members of the asked group may simply not know the answer. No response is not the same as being ignored, though admittedly it's hard to spot the difference from outside.


Please don't just post "help" endlessly, people will get annoyed.
Topic archived. No new replies allowed.