473,395 Members | 1,629 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Cross-specialization template member function friends

3
If templates worked how I would like them to work, I'd be able to do the following:

Expand|Select|Wrap|Line Numbers
  1. template <int N>
  2. class A
  3. {
  4.   private:
  5.     int X[N];
  6.   public:
  7.     template <int M>
  8.     void foo(const A<M> &Src) { X[N - 1] = Src.X[M - 1]; }
  9.  
  10.     template <int M>
  11.     friend void A<M>::foo(const A<N> &Src);
  12. };
  13.  
  14. int main(void)
  15. {
  16.   A<3> A3;
  17.   A<4> A4;
  18.   A3.foo(A4);
  19. }
It appears that templates do not in fact work like how I would like them to work, and GCC (4.1.2) comes up with a laundry-list of complaints:
Expand|Select|Wrap|Line Numbers
  1. templtest.cpp: In instantiation of "A<3>":
  2. templtest.cpp:16:   instantiated from here
  3. templtest.cpp:11: error: prototype for "void A<N>::foo(const A<3>&)" does not match any in class "A<N>"
  4. templtest.cpp:8: error: candidate is: template<int N> template<int M> void A::foo(const A<M>&)
  5. templtest.cpp: In instantiation of "A<4>":
  6. templtest.cpp:17:   instantiated from here
  7. templtest.cpp:11: error: prototype for "void A<N>::foo(const A<4>&)" does not match any in class "A<N>"
  8. templtest.cpp:11: error: candidates are: void A<N>::foo(const A<3>&)
  9. templtest.cpp:8: error:                 template<int N> template<int M> void A::foo(const A<M>&)
  10. templtest.cpp: In member function "void A<N>::foo(const A<M>&) [with int M = 4, int N = 3]":
  11. templtest.cpp:18:   instantiated from here
  12. templtest.cpp:5: error: "int A<4>::X [4]" is private
  13. templtest.cpp:8: error: within this context
The only one that vaugely seems sensible is the "private" one, but only because it can't seem to figure out the friend line.

After trying dozens of ways of coding this concept, the closest I've got to getting it to work is the following:
Expand|Select|Wrap|Line Numbers
  1. template <int N> class A;
  2. template <int N, int M> void do_foo(const A<M> &Src, A<N> &Dest);
  3.  
  4. template <int N>
  5. class A
  6. {
  7.   private:
  8.     int X[N];
  9.   public:
  10.     template <int M>
  11.     void foo(const A<M> &Src) { do_foo(Src, *this); }
  12.  
  13.     template <int M>
  14.     friend void do_foo(const A<M> &Src, A<N> &Dest);
  15. };
  16.  
  17. template <int N, int M> void do_foo(const A<M> &Src, A<N> &Dest)
  18. {
  19.   Dest.X[N - 1] = Src.X[M - 1];
  20. }
  21.  
  22. int main(void)
  23. {
  24.   A<3> A3;
  25.   A<4> A4;
  26.   A3.foo(A4);
  27. }
which "only" has a link error (do_foo doesn't get instantiated, so possibly this suppresses the other errors). Shuffling things around and/or adding prototypes to above the class definition doesn't help with this.

Is there any way to get this to work, or should I just keep with the stop-gap solution of making X public?
Feb 12 '08 #1
5 1747
weaknessforcats
9,208 Expert Mod 8TB
Your final example compiles and links OK with Visual Studio.NET 2005.

You might read up on bound vs unbound friend template functions. That would explain why you have to do what you did.
Feb 12 '08 #2
emboss
3
Your final example compiles and links OK with Visual Studio.NET 2005.
Well, it's either a GCC bug or a MSVC bug then :) Which doesn't really help me that much as I need to do this using GCC. As an aside, it also causes a linker error on Sun's compiler.

You might read up on bound vs unbound friend template functions. That would explain why you have to do what you did.
As I understand it, I've got a bound member function of an unbound class. As a result, the friend declarations effectively happen at the point of instantiation, and are, at that point, unbound (class) member function friends. The instantiation of A<3>::foo(const A<4> &) doesn't occur until the line "A3.foo(A4)", at which point it it matched against A<4>'s friend delaration (which effectively happen on the preceeding line with the instantiation of A<4>) and everything flows along smoothly.

However, upon careful re-reading of the C++ standard, it appears that there is a different problem: the standard doesn't allow for template class member functions to be friends of a template class. It only allows for template class member functions to be friends of a non-template class (14.5.3/6). Though I'm not sure why GCC doesn't flag the line as such, rather than reporting a lookup error.

Are these interpretations correct?
Feb 13 '08 #3
weaknessforcats
9,208 Expert Mod 8TB
Member functions can't be friend functions.
Feb 13 '08 #4
emboss
3
Member functions can't be friend functions.
Although this is how I read it, the developers of all the C++ compilers I could get my hands on (GCC, SunCC, MSVC) disagree. However, exactly what you can have as a member friend function varies substantially across the compilers. I got bored and brute-forced a whole lot of combinations. The results are quite interesting:

Expand|Select|Wrap|Line Numbers
  1. template <class T> class A;
  2.  
  3. class X { };
  4.  
  5. class B
  6. {
  7.   public:
  8.     void foo(void);
  9.     template <class S> void baz(S &Param);
  10. };
  11.  
  12. template <class T>
  13. class C
  14. {
  15.   public:
  16.     void foo(void);
  17.     void bar(T &Param);
  18.     template <class S> void baz(S &Param);
  19. };
  20.  
  21. template <class T>
  22. class A
  23. {
  24.   public:
  25.     void foo(void);
  26.     void bar(A<T> &Param);
  27.     template <class S> void baz(S &Param);
  28.  
  29.     // G = GCC 4.1.2 (3.4.3 behaves identically).
  30.     // S = SunCC 5.8
  31.     // M = MSVC 2005
  32.     //                                                     S G M
  33.     friend void B::foo(void);                           // Y Y Y
  34.     friend void B::baz<X>(X &);                         // Y Y N
  35.     friend void B::baz<T>(T &);                         // Y Y N
  36.     friend void B::baz<A<X> >(A<X> &);                  // Y Y N
  37.     friend void B::baz<A<T> >(A<T> &);                  // N Y N
  38.     template <class S> friend void B::baz(S &Param);    // Y Y Y
  39.  
  40.     friend void C<T>::foo(void);                        // Y Y Y
  41.     friend void C<T>::bar(T &);                         // Y Y Y
  42.     friend void C<T>::bar(X &);                         // Y Y N
  43.     friend void C<T>::baz<X>(X &);                      // Y N N
  44.     friend void C<T>::baz<T>(T &);                      // Y N N
  45.     friend void C<T>::baz<A<X> >(A<X> &);               // Y N N
  46.     friend void C<T>::baz<A<T> >(A<T> &);               // Y N N
  47.     template <class S> friend void C<T>::baz(S &Param); // N Y N
  48.     template <class S> friend void C<S>::baz(T &Param); // N N N
  49.  
  50.     template <class R>
  51.     friend void C<R>::foo(void);                        // Y Y N
  52.     template <class R>
  53.     friend void C<R>::bar(T &);                         // Y N N
  54.     template <class R>
  55.     friend void C<R>::bar(X &);                         // N Y N
  56.     template <class R>
  57.     friend void C<R>::baz<X>(X &);                      // N N N
  58.     template <class R>
  59.     friend void C<R>::baz<T>(T &);                      // N N N
  60.     template <class R>
  61.     friend void C<R>::baz<A<X> >(A<X> &);               // N N N
  62.     template <class R>
  63.     friend void C<R>::baz<A<T> >(A<T> &);               // N N N
  64.     template <class R>
  65.     template <class S> friend void C<R>::baz(S &Param); // N Y N
  66.     template <class R>
  67.     template <class S> friend void C<S>::baz(R &Param); // Y Y N
  68.  
  69.     template <class R>
  70.     friend void A<R>::foo(void);                        // Y Y N
  71.     template <class R>
  72.     friend void A<R>::bar(T &);                         // N N N
  73.     template <class R>
  74.     friend void A<R>::bar(X &);                         // N Y N
  75.     template <class R>
  76.     friend void A<R>::baz<X>(X &);                      // N N N
  77.     template <class R>
  78.     friend void A<R>::baz<T>(T &);                      // N N N
  79.     template <class R>
  80.     friend void A<R>::baz<A<X> >(A<X> &);               // N N N
  81.     template <class R>
  82.     friend void A<R>::baz<A<T> >(A<T> &);               // N N N
  83.     template <class R>
  84.     template <class S> friend void A<R>::baz(S &Param); // N Y N
  85.     template <class R>
  86.     template <class S> friend void A<S>::baz(R &Param); // Y Y N
  87. };
  88.  
  89. int main(void)
  90. {
  91.   A<X> AX;
  92.   return 0;
  93. }
Quite possibly my syntax is wrong for some of these options, or reordering/explicit instantiation would allow some of these to work - corrections would be appreciated. In any case, there is clearly a substantial difference in opinions as to how templates and friends should interact, and as mentioned all of these cases appear to be in violation of the standard.

Where's a language lawyer when you need one ... :)
Feb 13 '08 #5
weaknessforcats
9,208 Expert Mod 8TB
The problem with member funcitons being friends is that the friend is seen by the compiler as an override with no access to the original funciton.

You see, the override occurs when two member funcitons have the same name, argument list and amybe return type depending on whether you compiler supports covariance.

So, to do the override, your class have to inherit the function and that obviates the need to call it a friend since you can just call the funciton.
Feb 14 '08 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

0
by: Web Science | last post by:
Site and Features: http://www.eigensearch.com Search engine, eigenMethod, eigenvector, mathematical, manifolds, science, technical, search tools, eigenmath, Jacobian, quantum, mechanics,...
12
by: * ProteanThread * | last post by:
but depends upon the clique: ...
3
by: rollasoc | last post by:
Hi, Doing a bit of system testing on a Windows 98 laptop. (.Net 1.1 app). Did a bit of testing. Loaded a previously saved file. A gray box appeared with the text and buttons all white...
0
by: Web Science | last post by:
Site and Features: http://www.eigensearch.com Search engine, eigenMethod, eigenvector, mathematical, manifolds, science, technical, search tools, eigenmath, Jacobian, quantum, mechanics,...
4
by: David Peach | last post by:
Hello, hope somebody here can help me... I have a query that lists defects recorded in a user defined date range. That query is then used as the source for a Cross Tab query that cross-tabs count...
0
by: Web Science | last post by:
Site and Features: http://www.eigensearch.com Search engine, eigenMethod, eigenvector, mathematical, manifolds, science, technical, search tools, eigenmath, Jacobian, quantum, mechanics,...
7
by: Scott M. | last post by:
How can I disable the cross-site scripting check for one particular page of a site?
1
by: Rob Woodworth | last post by:
Hi, I'm having serious problems getting my report to work. I need to generate a timesheet report which will contain info for one employee between certain dates (one week's worth of dates). I...
6
by: Bart Van der Donck | last post by:
Hello, I'm presenting my new library 'AJAX Cross Domain' - a javascript extension that allows to perform cross-domain AJAX requests. http://www.ajax-cross-domain.com/ Any comments or...
6
by: ampo | last post by:
Hello. Can anyone help with cross-domain problem? I have HTML page from server1 that send xmlHTTPRequest to server2. How can I do it? Thanks.
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.