|
|
 |
 |
 |
 |
operator<< for standard output and templates
Hi everyone, I was unable to find out why my code is not compiling. I have a template class and I'm trying to write the operator<< for standard output. Does anyone know why this is not right? The code is as follows... // main class: template < class Individual, class SelectionPolicy, template <class> class CrossOverPolicy = OnePointX, class StoragePolicy = VectorPolicy<Individual>
class Population : public SelectionPolicy, public CrossOverPolicy<Individual> { // member variables and functions // friend declaration for standard output template <class I,class Se,template <class> class C,class St> friend ostream& operator<<(ostream& os, Population<I,Se,C,St>& pop); };
// operator<< definition template <class Individual,class SelectionPolicy,template <class> class CrossOverPolicy,class StoragePolicy> ostream& operator<<(ostream& os, Population<Individual,SelectionPolicy,CrossOverPolicy,StoragePolicy>& pop) { os<<"pop"<<endl; return os; }
// main function int main(){ typedef Population<ind, t > pop; pop ccc(10); cout<<ccc<<endl; return 0; }
The compiler error message is: main.cxx:104: error: ambiguous overload for 'operator<<' in 'std::cout << ccc' gaPopulation.h:411: note: candidates are: std::ostream& operator<<(std::ostream&, Population<I, Se, C, St>&) [with I = Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator>, Se = TournamentSelector<2>, C = OnePointX, St = VectorPolicy<Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator> >, Individual = Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator>, SelectionPolicy = TournamentSelector<2>, CrossOverPolicy = OnePointX, StoragePolicy = VectorPolicy<Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator> >]
gaPopulation.h:441: note: std::ostream& operator<<(std::ostream&, Population<Individual, SelectionPolicy, CrossOverPolicy, StoragePolicy>&) [with Individual = Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator>, SelectionPolicy = TournamentSelector<2>, CrossOverPolicy = OnePointX, StoragePolicy = VectorPolicy<Individual<Chromosome<Objective<1u, Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator> >]
make[2]: *** [main.o] Error 1 Thank you, a^2
On Jun 4, 12:32 am, aaragon <alejandro.ara@gmail.com> wrote: > I was unable to find out why my code is not compiling. I have a > template class and I'm trying to write the operator<< for standard > output. Does anyone know why this is not right? The code is as > follows...
Classical problem... > // main class: > template < > class Individual, > class SelectionPolicy, > template <class> class CrossOverPolicy = OnePointX, > class StoragePolicy = VectorPolicy<Individual> > class Population : public SelectionPolicy, public > CrossOverPolicy<Individual> { > // member variables and functions > // friend declaration for standard output > template <class I,class Se,template <class> class C,class St> > friend ostream& operator<<(ostream& os, Population<I,Se,C,St>& pop);
Here you declare for each instantiation of the template a non-template function, which takes the specific instance. This is the function that the compiler will try to call when you use << on the object. > }; > // operator<< definition > template <class Individual,class SelectionPolicy,template <class> > class CrossOverPolicy,class StoragePolicy> > ostream& operator<<(ostream& os, > Population<Individual,SelectionPolicy,CrossOverPolicy,StoragePolicy>& > pop) { > os<<"pop"<<endl; > return os; > }
And here you've just defined a function template. You now have two possible functions which can be called with <<. > // main function > int main(){ > typedef Population<ind, t > pop; > pop ccc(10); > cout<<ccc<<endl;
The compiler sees the two functions, the template, and the non-template. Both are equal matches, so the non-template is chosen. And you don't have a definition of it, so the linker complains.
> return 0; > } > The compiler error message is: > main.cxx:104: error: ambiguous overload for 'operator<<' in 'std::cout > << ccc' > gaPopulation.h:411: note: candidates are: std::ostream& > operator<<(std::ostream&, Population<I, Se, C, St>&) [with I = > Individual<Chromosome<Objective<1u, Optimizator<minimize> >, > BitSetPolicy, 2>, ClockMutator>, Se = TournamentSelector<2>, C = > OnePointX, St = VectorPolicy<Individual<Chromosome<Objective<1u, > Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator> >, Individual > = Individual<Chromosome<Objective<1u, Optimizator<minimize> >, > BitSetPolicy, 2>, ClockMutator>, SelectionPolicy = > TournamentSelector<2>, CrossOverPolicy = OnePointX, StoragePolicy = > VectorPolicy<Individual<Chromosome<Objective<1u, Optimizator<minimize>>, BitSetPolicy, 2>, ClockMutator> >]
I wouldn't have expected ambiguous. All other things being equal, the compiler should prefer the non-template over the template. Of course, that would just give you a linker error, so you wouldn't get much further. There are two simple solutions: provide the definition for the operator<< in the friend declaration, or provide a non-friend template function outside the class. (A non-friend or the operator<< definition in the class can, of course, call other member functions, e.g. you provide a member print(std::ostream&), which is called by the template function operator<<.) -- James Kanze (Gabi Software) email: james.ka@gmail.com Conseils en informatique oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
On Jun 3, 6:38 pm, James Kanze <james.ka@gmail.com> wrote:
> On Jun 4, 12:32 am, aaragon <alejandro.ara @gmail.com> wrote: > > I was unable to find out why my code is not compiling. I have a > > template class and I'm trying to write the operator<< for standard > > output. Does anyone know why this is not right? The code is as > > follows... > Classical problem... > > // main class: > > template < > > class Individual, > > class SelectionPolicy, > > template <class> class CrossOverPolicy = OnePointX, > > class StoragePolicy = VectorPolicy<Individual> > > class Population : public SelectionPolicy, public > > CrossOverPolicy<Individual> { > > // member variables and functions > > // friend declaration for standard output > > template <class I,class Se,template <class> class C,class St> > > friend ostream& operator<<(ostream& os, Population<I,Se,C,St>& pop); > Here you declare for each instantiation of the template a > non-template function, which takes the specific instance. This > is the function that the compiler will try to call when you use > << on the object. > > }; > > // operator<< definition > > template <class Individual,class SelectionPolicy,template <class> > > class CrossOverPolicy,class StoragePolicy> > > ostream& operator<<(ostream& os, > > Population<Individual,SelectionPolicy,CrossOverPolicy,StoragePolicy>& > > pop) { > > os<<"pop"<<endl; > > return os; > > } > And here you've just defined a function template. You now have > two possible functions which can be called with <<. > > // main function > > int main(){ > > typedef Population<ind, t > pop; > > pop ccc(10); > > cout<<ccc<<endl; > The compiler sees the two functions, the template, and the > non-template. Both are equal matches, so the non-template is > chosen. And you don't have a definition of it, so the linker > complains. > > return 0; > > } > > The compiler error message is: > > main.cxx:104: error: ambiguous overload for 'operator<<' in 'std::cout > > << ccc' > > gaPopulation.h:411: note: candidates are: std::ostream& > > operator<<(std::ostream&, Population<I, Se, C, St>&) [with I = > > Individual<Chromosome<Objective<1u, Optimizator<minimize> >, > > BitSetPolicy, 2>, ClockMutator>, Se = TournamentSelector<2>, C = > > OnePointX, St = VectorPolicy<Individual<Chromosome<Objective<1u, > > Optimizator<minimize> >, BitSetPolicy, 2>, ClockMutator> >, Individual > > = Individual<Chromosome<Objective<1u, Optimizator<minimize> >, > > BitSetPolicy, 2>, ClockMutator>, SelectionPolicy = > > TournamentSelector<2>, CrossOverPolicy = OnePointX, StoragePolicy = > > VectorPolicy<Individual<Chromosome<Objective<1u, Optimizator<minimize>>, BitSetPolicy, 2>, ClockMutator> >] > I wouldn't have expected ambiguous. All other things being > equal, the compiler should prefer the non-template over the > template. Of course, that would just give you a linker error, > so you wouldn't get much further. > There are two simple solutions: provide the definition for the > operator<< in the friend declaration, or provide a non-friend > template function outside the class. (A non-friend or the > operator<< definition in the class can, of course, call other > member functions, e.g. you provide a member > print(std::ostream&), which is called by the template function > operator<<.) > -- > James Kanze (Gabi Software) email: james.ka@gmail.com > Conseils en informatique oriente objet/ > Beratung in objektorientierter Datenverarbeitung > 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
Thank you James for your answer, I tried both ways and they work. Something that I don't really understand is why the friend declaration within the class is a non-template declaration? If you put the template <template parameters> before the keyword 'friend', aren't you declaring this as a template function? Once again, thanks for the answer.
On Jun 4, 6:34 am, aaragon <alejandro.ara@gmail.com> wrote:
> On Jun 3, 6:38 pm, James Kanze <james.ka @gmail.com> wrote: > > On Jun 4, 12:32 am, aaragon <alejandro.ara @gmail.com> wrote: > > > I was unable to find out why my code is not compiling. I have a > > > template class and I'm trying to write the operator<< for standard > > > output. Does anyone know why this is not right? The code is as > > > follows... > > Classical problem... > > > // main class: > > > template < > > > class Individual, > > > class SelectionPolicy, > > > template <class> class CrossOverPolicy = OnePointX, > > > class StoragePolicy = VectorPolicy<Individual> > > > class Population : public SelectionPolicy, public > > > CrossOverPolicy<Individual> { > > > // member variables and functions > > > // friend declaration for standard output > > > template <class I,class Se,template <class> class C,class St> > > > friend ostream& operator<<(ostream& os, Population<I,Se,C,St>& pop); > > Here you declare for each instantiation of the template a > > non-template function, which takes the specific instance. This > > is the function that the compiler will try to call when you use > > << on the object. > > > }; [...] > > There are two simple solutions: provide the definition for the > > operator<< in the friend declaration, or provide a non-friend > > template function outside the class. (A non-friend or the > > operator<< definition in the class can, of course, call other > > member functions, e.g. you provide a member > > print(std::ostream&), which is called by the template function > > operator<<.) > Thank you James for your answer, I tried both ways and they work. > Something that I don't really understand is why the friend declaration > within the class is a non-template declaration? If you put the > template <template parameters> before the keyword 'friend', aren't you > declaring this as a template function? > Once again, thanks for the answer.
I missed them. Originally, templates couldn't be friends; this possibility was added to the standard. And in fact, the standard actually contradicts itself here: the first sentence of 11.4 (Friends) says that a friend is a function or a class that is not a member of the class, and templates are neither functions nor classes. 14.5.3 (Friends, but in the chapter on templates), says that a friend can be a function template or class template, a specialization of a function template or class template, or an ordinary (nontemplate) function or class. There's a definite contradiction there. I'm not sure what the compiler is doing in your case. As I said, I was surprised that it found an ambiguty. If I understand your code correctly, it should declare all of the specializations of the template function as friend. There is also a syntax to declare just a particular instantiation as friend, something like: friend ostream& operator<< <>( ... ) ; I think (although maybe the declaration of the template must precede the class definition). I'm not really sure, however, as I always use one of the techniques I mentionned in my first post. -- James Kanze (GABI Software) email:james.ka@gmail.com Conseils en informatique oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
On Jun 4, 2:16 am, James Kanze <james.ka@gmail.com> wrote:
> On Jun 4, 6:34 am, aaragon <alejandro.ara @gmail.com> wrote: > > On Jun 3, 6:38 pm, James Kanze <james.ka@gmail.com> wrote: > > > On Jun 4, 12:32 am, aaragon <alejandro.ara@gmail.com> wrote: > > > > I was unable to find out why my code is not compiling. I have a > > > > template class and I'm trying to write the operator<< for standard > > > > output. Does anyone know why this is not right? The code is as > > > > follows... > > > Classical problem... > > > > // main class: > > > > template < > > > > class Individual, > > > > class SelectionPolicy, > > > > template <class> class CrossOverPolicy = OnePointX, > > > > class StoragePolicy = VectorPolicy<Individual> > > > > class Population : public SelectionPolicy, public > > > > CrossOverPolicy<Individual> { > > > > // member variables and functions > > > > // friend declaration for standard output > > > > template <class I,class Se,template <class> class C,class St> > > > > friend ostream& operator<<(ostream& os, Population<I,Se,C,St>& pop); > > > Here you declare for each instantiation of the template a > > > non-template function, which takes the specific instance. This > > > is the function that the compiler will try to call when you use > > > << on the object. > > > > }; > [...] > > > There are two simple solutions: provide the definition for the > > > operator<< in the friend declaration, or provide a non-friend > > > template function outside the class. (A non-friend or the > > > operator<< definition in the class can, of course, call other > > > member functions, e.g. you provide a member > > > print(std::ostream&), which is called by the template function > > > operator<<.) > > Thank you James for your answer, I tried both ways and they work. > > Something that I don't really understand is why the friend declaration > > within the class is a non-template declaration? If you put the > > template <template parameters> before the keyword 'friend', aren't you > > declaring this as a template function? > > Once again, thanks for the answer. > I missed them. Originally, templates couldn't be friends; this > possibility was added to the standard. And in fact, the > standard actually contradicts itself here: the first sentence of > 11.4 (Friends) says that a friend is a function or a class that > is not a member of the class, and templates are neither > functions nor classes. 14.5.3 (Friends, but in the chapter on > templates), says that a friend can be a function template or > class template, a specialization of a function template or class > template, or an ordinary (nontemplate) function or class. > There's a definite contradiction there. > I'm not sure what the compiler is doing in your case. As I > said, I was surprised that it found an ambiguty. If I > understand your code correctly, it should declare all of the > specializations of the template function as friend. There is > also a syntax to declare just a particular instantiation as > friend, something like: > friend ostream& operator<< <>( ... ) ; > I think (although maybe the declaration of the template must > precede the class definition). I'm not really sure, however, as > I always use one of the techniques I mentionned in my first > post. > -- > James Kanze (GABI Software) email:james.ka@gmail.com > Conseils en informatique oriente objet/ > Beratung in objektorientierter Datenverarbeitung > 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
James, thank you once again for your insight on this, it has been very helpful.
|
 |
 |
 |
 |
|