.NET Forum / Languages / Managed C++ / February 2005
OK in Visual C++6.0 but not in Visual C++ .NET 2003?
|
|
Thread rating:  |
hihaho - 06 Feb 2005 10:43 GMT I had a template library, the library was successfully compiled on versrion 6.0 but when I tried to upgrade it in .NET version, compilation had failed with the message like:
error C2248 'MyPLib::Basic2DArray<T>::m' : cannot access protected member declared in 'PLib::Basic2DArray<T>'
The class implemented by
template <class T> class Basic2DArray { public: ... friend void InitializeArray(Basic2DArray<T>& a); ... protected: int m; }
Why the code was not compiled in .NET version? In Visual C++ 6.0, the library had no problem with compilation and link. Please help me...
Antti Keskinen - 06 Feb 2005 11:26 GMT Hello !
Visual C++ .NET has much stricter standard compliance than VS 6.0.
Your class declaration shows that you create a friend function InitializeArray for Basic2DArray. This means that the InitializeArray function can access the protected and private members of Basic2DArray. However, the error code shows that you're trying to access the protected member from somewhere where you ain't supposed to.
Double-clicking on the error would have shown you the line in which you're trying to access it. If you would've copied this line as a part of the message, I could've answered if you're doing something wrong.
Remember that declaring a friend function InitializeArray requires that the definition of the function must be precisely alike. Could it be that you forgot the template directive from the function declaration ? Or a similar problem ?
Without more details, helping is quite difficult.
-Antti Keskinen
>I had a template library, the library was successfully compiled > on versrion 6.0 but when I tried to upgrade it in .NET version, [quoted text clipped - 19 lines] > the library had no problem with compilation and link. > Please help me... hihaho - 06 Feb 2005 12:13 GMT Could you do me a favor? It is very lenthy to list details here, so it will be very appreciated of you to try comile the following libray: From the following link, http://sourceforge.net/projects/libnurbs/ After downloading the "nurbs++=3.0.11" library and Unzipping it, please try to build one of the projects in the examples folder. You may have to modify the project to load in the Visual C++ .NET environment...
Thank you very much in advance!
Carl Daniel [VC++ MVP] - 06 Feb 2005 15:14 GMT > I had a template library, the library was successfully compiled > on versrion 6.0 but when I tried to upgrade it in .NET version, [quoted text clipped - 18 lines] > Why the code was not compiled in .NET version? In Visual C++ 6.0, > the library had no problem with compilation and link. The problem is that your code isn't standard compliant so it shouldn't compile.
When you write
template <class T> class X { friend void f(X<T>&); };
you're declaring a namespace-scoped non-template function f(X<T>&) as a friend.
When you subsequently write (you didn't show this, but I'm betting this is what you did)
template <class T> void f(X<T>&) { }
You're defining a template function. Under VC7 and before, the compiler could not distinguish between instantiations of a template function like the above and a non-template function with the same signature, so your code "worked".
An example:
X<int> declares f(X<int>&) as a friend. VC6 could not tell the difference between the <int> instantiation of a function template:
void f<int>(X<int>&);
and a non-template function
void f(X<int>&);
VC7.1 (.NET 2003) fixes this compiler bug, which breaks your code. So, what are you to do? You have to declare your friend a little differently in order to declare am instantiation of a function template as a friend:
// forward-declare the class template template <class T> class X;
// forward-declare the function template template <class T> void f(X<T>&);
// actual class definition template <class T> class X { friend void f<T>(X&); };
// actual function definition template <class T> void f(X<T>&) { }
This makes f<T>(X<T>&) a friend of X<T>. It doesn't make any like-named non-template functions friends, it also doesn't make f<U>(X<T>&) a friend of X<T> (only instantiations with the same template argument list are friend).
HTH
-cd
Antti Keskinen - 06 Feb 2005 20:14 GMT Hi !
The example you showed declared function template to be a friend of a class template, correct ?
However, consider the following:
template<typename T> class MyClass { friend void InitClass(MyClass<T>& refClass); };
void InitClass(MyClass<T>& ref) { }
I believe this would result in an error with 'undefined variable T', yes ? Would it be correct to move the function definition above the class definition, mark it as a templated function, and forward-declare the class template, like in
template<typename T> class MyClass;
template<typename T> void InitClass(MyClass<T>& refClass) { }
template<typename T> class MyClass { friend void InitClass(MyClass<T>& refClass); };
This would be the same thing you did, but with different semantics, no ? How would you tackle the situation of "declaring/defining a non-templated function, which takes an instantated MyClass of any type as a parameter" ? Or is this impossible due to the fact that non-templated functions cannot take "any type" parameters ? If it's a non-templated function, is the only possibility to declare it for a defined set of types, as in:
template<typename T> class MyClass { friend void InitClass(MyClass<T>& refClass); };
void InitClass(MyClass<int>& refClass) { }
void InitClass(MyClass<double>& refClass) { }
void InitClass(MyClass<char>& refClass) { }
This would result in InitClass being a friend of MyClass<T> in cases where T was of 'int', 'double' or 'long' type, but in other cases it would not be a friend, correct ?
I know this sounds difficult and might feel irrelevant, but I'm just intrigued by the template semantics, i.e. what does it actually mean to use a template :)
-Antti Keskinen
> The problem is that your code isn't standard compliant so it shouldn't > compile. [quoted text clipped - 65 lines] > > -cd Carl Daniel [VC++ MVP] - 07 Feb 2005 00:35 GMT > Hi ! > > The example you showed declared function template to be a friend of a > class template, correct ? More precisely, it declared an instantion of a function template to be a friend of an instantiation of a class template. Templates themselves have no friends (so to speak).
> However, consider the following: > [quoted text clipped - 10 lines] > I believe this would result in an error with 'undefined variable T', > yes ? Correct.
> Would it be correct to move the function definition above the > class definition, mark it as a templated function, and [quoted text clipped - 13 lines] > friend void InitClass(MyClass<T>& refClass); > }; Not quite.
friend void InitClass<T>(MyClass&);
If you don't use the InitClass<T> syntax, you're declaring a non-member friend that's defined in the enclosing namespace. Even though there's a template that matches the name and parameter list, it's not the friend unless you use one of two syntaxes:
as above - an instantiation of the function template is a friend
template<class T> friend void InitClass(MyClass<T>&); - all instantiations of the InitClass function template are friends of MyClass<T>.
> This would be the same thing you did, but with different semantics, > no ? How would you tackle the situation of "declaring/defining a > non-templated function, which takes an instantated MyClass of any > type as a parameter" ? Not possible, as you surmize. But the template friend declaration above makes all instantions of a function template friends of the enclosing class template.
> Or is this impossible due to the fact that > non-templated functions cannot take "any type" parameters ? If it's a [quoted text clipped - 21 lines] > where T was of 'int', 'double' or 'long' type, but in other cases it > would not be a friend, correct ? Right.
> I know this sounds difficult and might feel irrelevant, but I'm just > intrigued by the template semantics, i.e. what does it actually mean > to use a template :) It's a good thing to understand - and an obscure corner of the language. There are many possibilities when you mix templates and friends and it definitely helps to know what each combination means.
-cd
Antti Keskinen - 07 Feb 2005 08:18 GMT Hello !
A few more questions to help me clarify certain issues. In your previous post, you used the syntax
friend void InitClass<T>(MyClass&);
to declare all InitClass<T> instantations as friends of MyClass<T> (so that InitClass<U> is not a friend of MyClass<T>).
However, the curious thing about this comes from the parameter list. If I had rewritten the friend declaration inside the class as
friend void InitClass<T>(MyClass<T>& refClass);
then how would this change the situation of who's a friend and who's not ? Or is it just a "syntax error" situation ? Or is the <T> unrequired in the parameter list because we are not talking about template declaration, but an instantation of it, as in, the <T> gets "copied" into the place where the template definition specifies it should go ?
Moreover, when writing the following:
template<typename T> class MyClass;
template<typename T> void InitClass(MyClass<T>& refClass) { }
template<typename T> class MyClass { template<typename T> friend void InitClass(MyClass<T>& refClass); };
Does the 'friend' keyword ensure that InitClass doesn't become some sort of a nested-template declaration ? So this syntax means that all InitClass instantations are friends of MyClass<T>, meaning, an InitClass<int> can access MyClass<double>'s private/protected members ?
Also, if using a syntax like above, is it necessary to forward-declare the MyClass<T> template before the function template ? Like, if I used the "nested-template-looking" friend declaration of InitClass, I could move the actual InitClass<T> definition to after or before the class definition, and would not need any class declarations ?
Again, thank you for answering these questions. Like you stated, templates are really one of the darkest corners of C++. But, very rewarding as well :D
-Antti Keskinen
>> Hi ! >> [quoted text clipped - 101 lines] > > -cd Carl Daniel [VC++ MVP] - 07 Feb 2005 14:39 GMT > Hello ! > [quoted text clipped - 5 lines] > to declare all InitClass<T> instantations as friends of MyClass<T> > (so that InitClass<U> is not a friend of MyClass<T>). The instantion of the InitClass function template with template argument <T> is a friend of the instantiation of the MyClass template with template arguments <T>.
> However, the curious thing about this comes from the parameter list. > If I had rewritten the friend declaration inside the class as > > friend void InitClass<T>(MyClass<T>& refClass); They're equivalent. Within the definition of a class template, the name of the template without a template argument list is synonymous with the fully specified name. i.e. MyClass and MyClass<T> are the same.
> then how would this change the situation of who's a friend and who's > not ? Or is it just a "syntax error" situation ? Or is the <T> > unrequired in the parameter list because we are not talking about > template declaration, but an instantation of it, as in, the <T> gets > "copied" into the place where the template definition specifies it > should go ? Exactly.
> Moreover, when writing the following: > [quoted text clipped - 17 lines] > InitClass<int> can access MyClass<double>'s private/protected members > ? Correct.
> Also, if using a syntax like above, is it necessary to > forward-declare the MyClass<T> template before the function template > ? Like, if I used the "nested-template-looking" friend declaration of > InitClass, I could move the actual InitClass<T> definition to after > or before the class definition, and would not need any class > declarations ? It's necessary to forward-declare the class, otherwise it's impossible to specifiy the parameter list for the function since MyClass is undefined at that point.
> Again, thank you for answering these questions. Like you stated, > templates are really one of the darkest corners of C++. But, very > rewarding as well :D You're welcome!
-cd
Vladimir Nesterovsky - 07 Feb 2005 09:10 GMT Are you arguing that such compiler awareness whether friend function is template is correct? Doesn't this violate the very nature of templates to be transparently built into? I do believe that a following code should compile just fine (which is the case with Comeau C++ Online compiler):
template <class T> class X { friend void f(X<T>&);
int y; };
template <class T> void f(X<T>& x) { x.y = 1; }
int main() { X<int> x;
f(x); }
Do you have any spec references why shouldn't this work?
 Signature Vladimir Nesterovsky e-mail: vladimir@nesterovsky-bros.com home: www.nesterovsky-bros.com
> The problem is that your code isn't standard compliant so it shouldn't > compile. [quoted text clipped - 60 lines] > non-template functions friends, it also doesn't make f<U>(X<T>&) a friend of > X<T> (only instantiations with the same template argument list are friend). Carl Daniel [VC++ MVP] - 07 Feb 2005 14:58 GMT > Are you arguing that such compiler awareness whether friend function > is template is correct? Yes, it's correct.
> Doesn't this violate the very nature of templates to be transparently > built into? No, it's a quirk of friend declarations. When you write a friend declaration, if no matching function is already visible, then a suitable declaration is made in the enclosing scope, but that declaration is not a template unless the friend declaration names a template (template <class T> friend void f(X&)).. Templates don't have friends - instantiations of template have friends.
> I do believe that a following code should compile just fine (which is > the case with Comeau C++ Online compiler): Remember, the Comeau online compiler doesn't link. The function template f<T>(X<T>&) is never used in this program, so it's never instantiated. As a result, the compiler doesn't complain about the access to x.y. Since the online demo doesn't link, no error is generated for the namespace scoped
::f(X<int>&) that was implicitly declared by the friend declaration in the instantiation of X<int>.
> Do you have any spec references why shouldn't this work? The C++ Standard. If you make me quote chapter and verse I'll have to do some digging... but it's in there. Here are all the possibilitiies:
// Instantiation f<T> is a friend of instantiaion X<T>
template <class T> class X;
template <class T> void f(X<T>&);
template <class T> class X { friend void f<T>(X<T>&);
int m; };
template <class T> void f(X<T>& x) { x.m = 1;
// Illegal - instantiations of f are only // friends with a single instantiation of X // with the same template arguments. // reinterpret_cast<X<float>&>(x).m =1; }
// All instantiations of g<U> are friends of Y<T>
template <class T> class Y { template <class U> friend void g(Y&);
int m; };
template <class T> void g(Y<T>& y) { y.m = 1;
// Legal - all instantions of g<U> are friends // with all instantiations of Y<T> reinterpret_cast<Y<float>&>(y).m =1; }
// Non-template functions are friend of Z<T>
template <class T> class Z { friend void h(Z<T>&);
int m; };
void h(Z<int>& z) { z.m = 1; // Illegal - this h is only a friend of // Z<int>. // reinterpret_cast<Z<float>&>(z).m =1; }
void h(Z<float>& z) { z.m = 1; // Illegal - this h is only a friend of // Z<float>. // reinterpret_cast<Z<int>&>(z).m =1; }
int main() { X<int> x; f(x);
Y<int> y; g<int>(y);
Z<int> zi; h(zi); Z<float> zf; h(zf); }
-cd
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|