Prev: Is there any standard/guarantees for exception safety in STL operations?
Next: Is there any standard/guarantees for exception safety in STL operations?
From: DeMarcus on 25 Jul 2010 08:56 Hi, Consider this template. template<typename T> struct Q { virtual Q* fnc() { return new T; } }; If I now declare a variable like this Q<int> qi; I get the following from gcc 4.5.0. "error: cannot convert 'int*' to Q<int>*' in return". That seems perfectly correct. But now try this struct A : Q<int> { }; and it complies perfectly fine with gcc 4.5.0!!! That must be a bug, right? Thanks, Daniel -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: DeMarcus on 25 Jul 2010 23:13 On 2010-07-26 01:56, DeMarcus wrote: > Hi, > > Consider this template. > > template<typename T> > struct Q > { > virtual Q* fnc() { return new T; } > }; > > If I now declare a variable like this > > Q<int> qi; > > I get the following from gcc 4.5.0. > "error: cannot convert 'int*' to Q<int>*' in return". > > That seems perfectly correct. But now try this > > struct A : Q<int> > { > }; > > and it complies perfectly fine with gcc 4.5.0!!! That must be a bug, right? > > > Thanks, > Daniel > Ok, I realized I needed a bit compiler knowledge refresh. I found out that it's not until A is instantiated that the error will show up. Can you please confirm that the following is true? If I do the this struct A : Q<A> { }; the compiler will be able to deduce that A is a subclass of Q since the compiler compiles in two steps; first it goes through all the declarations and sees everything is ok, then it goes through all the definitions, and it will then find out that 'return T' is valid according to the already processed declarations where it says that A inherits from Q. (is there a paragraph in the standard confirming this?) Can you confirm that the following is correct as well? I extended the template to look like this. Note, I changed the fnc() return type be of type T. template<typename T, class Base> struct Q : Base { virtual T* fnc() { return new T; } }; I extended A with some inheritance. struct A : Q<A, EmptyClass> { }; struct B : Q<B, A> { }; The compiler will give me an error saying that B is not a covariant return type of A (while it actually is). Is the compiler unable to deduce the covariance because of the fact that it's only part of the declaration step? (would the compiler be able to find out, or do we break any rule by doing that?) If I remove the keyword 'virtual' it will work because the compiler then applies function overriding instead. Am I correct about how the compiler works? Thanks, Daniel -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 25 Jul 2010 23:11 On 26 Jul., 01:56, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > Hi, > > Consider this template. > > template<typename T> > struct Q > { > virtual Q* fnc() { return new T; } > > }; > > If I now declare a variable like this > > Q<int> qi; > > I get the following from gcc 4.5.0. > "error: cannot convert 'int*' to Q<int>*' in return". > > That seems perfectly correct. But now try this > > struct A : Q<int> > { > > }; > > and it complies perfectly fine with gcc 4.5.0!!! That must be a bug, right? This is not a bug, but an explicit freedom, the Standard provides to implementors of templates: In contrast to non-virtual functions, virtual functions may lead to an immediate member instantiation, even, if not used, see 14.7.1/9 (Both C++03 and FCD): "An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated." HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 26 Jul 2010 02:48 On 26 Jul., 16:11, Daniel Kr�gler <daniel.krueg...(a)googlemail.com> wrote: > In contrast to non-virtual functions, virtual functions > may lead to an immediate member instantiation, even, if not > used, see 14.7.1/9 (Both C++03 and FCD): And to be more precise: Any declaration of a virtual function is considered as a "use", see 3.2/2: "A virtual member function is used if it is not pure." HTH & Greetings from Bremen Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 26 Jul 2010 02:46
On Jul 26, 12:56 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > Consider this template. > template<typename T> > struct Q > { > virtual Q* fnc() { return new T; } > }; > If I now declare a variable like this > Q<int> qi; > I get the following from gcc 4.5.0. > "error: cannot convert 'int*' to Q<int>*' in return". > That seems perfectly correct. But now try this > struct A : Q<int> > { > }; > and it complies perfectly fine with gcc 4.5.0!!! That must be > a bug, right? No. The code is perfectly legal (and must be accepted by the compiler) as long as you don't try to instantiate A. The function Q<int>::fnc should only be instantiated (triggering the error) if it is used. A virtual function is "used" if there is an instance of the type, but as long as there is no instance, a compiler is not allowed to instantiate it. (A really clever compiler might be able to warn that there is no type T which could result in a valid fnc, but it can't trigger an error unless it is actually called on to instantiate fnc.) -- James Kanze -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |