Topic: Templated constructor or copy constructor


Author: Thomas Maeder <maeder@glue.ch>
Date: Sat, 2 Jan 2010 21:06:24 CST
Raw View
eldiener <eldiener@tropicsoft.com> writes:

> On Dec 31, 10:27 am, Thomas Maeder <mae...@glue.ch> wrote:
>> eldiener <eldie...@tropicsoft.com> writes:
>>
>> > I was told, by a Microsoft VC++ employee responding to my bug
>> > report, that the compiler-generated copy constructor of the Derived
>> > class finds the templated constructor of the Base class a better
>> > match than the compiler-generated copy constructor of the Base
>> > class.
>>
>> This is not correct.
>
> Is there a section of the C++ standard that explains this ?

Yes.

   12.8/8 of the 1998 Standard states that generated copy constructors
perform memberwise copies of the sub-objects, and that for a
sub-object of class type, that class type's copy constructor is used.


> For the record my original code is:

[too complex for me to understand]

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Sun, 3 Jan 2010 12:07:43 CST
Raw View
Thomas Maeder wrote:
> 12.8/8 of the 1998 Standard states that generated copy constructors
> perform memberwise copies of the sub-objects, and that for a
> sub-object of class type, that class type's copy constructor is used.

Thanks! The latest C++0x draft (N3000) says the very same, at 12.8 Copying
class objects [class.copy]:
> The implicitly-defined or explicitly-defaulted copy constructor
> for a non-union class X performs a memberwise copy of its subobjects.
...
> if the subobject is of class type, the copy constructor for the class
> is used;
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf

>> For the record my original code is:
> [too complex for me to understand]

FYI, I posted a simplified code example at microsoft.public.vc.language,
subject "Bug 522094, warning C4717 and stack overflow: please vote!"
http://groups.google.com/group/microsoft.public.vc.language/browse_frm/thread/627431c8aa75d50b

Now that we got the right citations from the C++ Standard, I think it's
preferable to further discuss the issue at a Microsoft specific site, like
microsoft.public.vc.language or
http://social.msdn.microsoft.com/Forums/en/vclanguage  Or just add your
comments to the bug report by Edward (eldiener):
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=522094


Kind regards,

  Niels
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Sun, 3 Jan 2010 12:06:55 CST
Raw View
On Jan 3, 3:07 am, "Niels Dekker - no reply address"
<inva...@this.is.invalid> wrote:
> eldiener wrote:

      [...]
> > In C++ I get a 'warning C4717:
> > 'AClassTemplate<double,YY>::AClassTemplate<double,YY>' : recursive on
> > all control paths, function will cause runtime stack overflow'.

> For the record, your bug report is publicly available  :-)
> Title: "warning C4717 'recursive on all control paths error'
> erroneous"https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx...

> And yes, I'm able to reproduce the issue.

And as Thomas Maeder has pointed out, the person commenting for
Microsoft in the bug report is wrong (although it is an
understandable error).  In a *compiler generated* copy
constructor, subobjects of class type (bases and members of
class type) are copied using the classes copy constructor,
explicitly.  If you provide a copy constructor for the derived
class, with something like:

     Dervived::Derived( Derived const& other )
         :   Base( other )
     {
     }

this doesn't hold; the compiler is required to choose the best
match, which will be your templated constructor (which, because
it takes a value, requires that the object be copied, invoking
the copy constructor, ad infinitum).  Compiler generated copy
constructors do not involve overload resolution; user written
ones do.

In the meantime, as a general rule, any time a class has a
templated constructor, it's probably best to provide a user
defined copy constructor as well.  Because even if Microsoft
fixes the bug, the day you have to provide a user defined copy
constructor for the derived class, it will bite you.

--
James Kanze

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Tue, 5 Jan 2010 17:20:21 CST
Raw View
CWG issue #535 ("Copy construction without a copy constructor") proposed
regarding an implicitly-defined copy-constructor of a derived class:

 Change 12.8 [class.copy] paragraph 8 as follows:
   ...Each subobject is copied in the manner appropriate to its type:
   * if the subobject is of class type,
     <DELETE> the copy constructor for the class is used </DELETE>
     <INSERT> direct-initialization (8.5 [dcl.init]) is performed
      [ Note: If overload resolution fails or the constructor selected
     by overload resolution is inaccessible (11 [class.access]) in
     the context of X, the program is ill-formed.
     --end note ] </INSERT>

The issue is under review:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#535

So is the following program well-defined, according to the proposed wording
of CWG issue #535?

 //////////////////////////////////////////////////
 class Bar
 {
 public:
   virtual ~Bar() {}
   Bar() {}
   template<typename U> explicit Bar(U) {}
 };

 class Foo : public Bar {};

 int main()
 {
   Foo foo1;
   Foo foo2 = foo1;
 }
 //////////////////////////////////////////////////

Should the implicitly-defined copy-constructor of Foo call the (explicit)
template constructor of its base class, Bar, according to CWG issue #535?

GCC currently has the implicitly-defined copy-constructor of Foo calling the
implicitly-defined copy-constructor of its base class, which is very much
the behavior I would prefer.

 Kind regards, Niels


PS Thanks to Leigh Johnston for his comments and CWG issue #535 reference,
added to the bug report by Edward Diener,
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=522094
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Wed, 6 Jan 2010 13:02:31 CST
Raw View
Niels Dekker - no reply address wrote:

> CWG issue #535 ("Copy construction without a copy constructor") proposed
> regarding an implicitly-defined copy-constructor of a derived class:
>
>  Change 12.8 [class.copy] paragraph 8 as follows:
>    ...Each subobject is copied in the manner appropriate to its type:
>    * if the subobject is of class type,
>      <DELETE> the copy constructor for the class is used </DELETE>
>      <INSERT> direct-initialization (8.5 [dcl.init]) is performed
>       [ Note: If overload resolution fails or the constructor selected
>      by overload resolution is inaccessible (11 [class.access]) in
>      the context of X, the program is ill-formed.
>      --end note ] </INSERT>
>
> The issue is under review:
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#535
>
> So is the following program well-defined, according to the proposed
> wording of CWG issue #535?
>
>  //////////////////////////////////////////////////
>  class Bar
>  {
>  public:
>    virtual ~Bar() {}
>    Bar() {}
>    template<typename U> explicit Bar(U) {}
>  };
>
>  class Foo : public Bar {};
>
>  int main()
>  {
>    Foo foo1;
>    Foo foo2 = foo1;
>  }
>  //////////////////////////////////////////////////
>
> Should the implicitly-defined copy-constructor of Foo call the (explicit)
> template constructor of its base class, Bar, according to CWG issue #535?
>

I think it should not call the template, because the call to the
constructors has to be done using the baseclass subobject of "foo1", which
has type "Bar". The template is not used then (it will never use a
constructor having a value parameter to copy "Bar" to a "Bar" object -
12.8/3). If the type of the argument was of type "Foo", it would be used.

GCC is, like msvc, not using only copy constructors. This can be seen by the
following code:

struct A {
   template<typename T> A(T&);
};

struct B : A { auto_ptr<int> p; };

B b1, b2(b1);

GCC uses the template, instantiating A::A<A>(A&) in preference to the
constructor - but as can be seen it uses "A" as argument, not "B".

I wanna thanks Leigh Johnston too, who was kind enough to forward my
opinions w.r.t this wrong argument of the constructor of "A" to that
bugreport since i wasn't registered there yet.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Wed, 6 Jan 2010 21:54:50 CST
Raw View
>> CWG issue #535 ("Copy construction without a copy constructor")
>> [...]
>> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#535

>> Should the implicitly-defined copy-constructor of Foo call the
>> (explicit) template constructor of its base class, Bar, according to
>> CWG issue #535?

Johannes Schaub (litb) wrote:
> I think it should not call the template, because the call to the
> constructors has to be done using the baseclass subobject of "foo1",
> which has type "Bar". The template is not used then (it will never
> use a constructor having a value parameter to copy "Bar" to a "Bar"
> object - 12.8/3). If the type of the argument was of type "Foo",
> it would be used.

Thanks, Johannes. I think that N3000, [class.copy], 12.8/3 does indeed apply
to my Foo/Bar example, as it says: "A member function template is never
instantiated to perform the copy of a class object to an object of its class
type."

> GCC is, like msvc, not using only copy constructors. This can
> be seen by the following code:
>
> struct A {
>   template<typename T> A(T&);
> };
>
> struct B : A { auto_ptr<int> p; };
>
> B b1, b2(b1);
>
> GCC uses the template, instantiating A::A<A>(A&) in preference to the
> constructor...

Thanks for the example! But doesn't GCC thereby violate [class.copy],
12.8/3? ("A member function template is never instantiated to perform the
copy of a class object to an object of its class type.", -- N3000)

I slightly modified your example, declaring A's constructor template
"explicit", and replacing the direct-initialization of b2 by
copy-initialization:

   //////////////////////////////////////////////////
   #include <iostream>
   #include <memory>
   using namespace std;

   struct A {
     A() {}
     template<typename T> explicit A(T&) {
       cout << "Explicit constructor template!" << endl;
     }
   };

   struct B : A { auto_ptr<int> p; };

   int main() {
     B b1;
     B b2 = b1;
   }
   //////////////////////////////////////////////////

To my surprise, the implicit copy-constructor of B kept calling A's
constructor template, at least on GCC 4.1.2: http://codepad.org/YB4AlSRQ

Personally I don't feel very comfortable about implicit copy-constructors
calling non-copy constructors. I'd be even more concerned if implicit
copy-constructors might call explicit (non-converting) constructors, as in
the example above. Does anybody share my concerns with respect to CWG #535?

Kind regards,

   Niels
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Thu, 7 Jan 2010 13:49:40 CST
Raw View
Niels Dekker - no reply address wrote:

>>> CWG issue #535 ("Copy construction without a copy constructor")
>>> [...]
>>> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#535
>
>>> Should the implicitly-defined copy-constructor of Foo call the
>>> (explicit) template constructor of its base class, Bar, according to
>>> CWG issue #535?
>
> Johannes Schaub (litb) wrote:
>> I think it should not call the template, because the call to the
>> constructors has to be done using the baseclass subobject of "foo1",
>> which has type "Bar". The template is not used then (it will never
>> use a constructor having a value parameter to copy "Bar" to a "Bar"
>> object - 12.8/3). If the type of the argument was of type "Foo",
>> it would be used.
>
> Thanks, Johannes. I think that N3000, [class.copy], 12.8/3 does indeed
> apply to my Foo/Bar example, as it says: "A member function template is
> never instantiated to perform the copy of a class object to an object of
> its class type."
>
>> GCC is, like msvc, not using only copy constructors. This can
>> be seen by the following code:
>>
>> struct A {
>>   template<typename T> A(T&);
>> };
>>
>> struct B : A { auto_ptr<int> p; };
>>
>> B b1, b2(b1);
>>
>> GCC uses the template, instantiating A::A<A>(A&) in preference to the
>> constructor...
>
> Thanks for the example! But doesn't GCC thereby violate [class.copy],
> 12.8/3? ("A member function template is never instantiated to perform the
> copy of a class object to an object of its class type.", -- N3000)
>

The intention when read together with footnote to 12.8/2 and the example
seems to be to only apply to cases that would violate the rule directly
preceeding that statement (i.e that a constructor having a non-reference
parameter is never instantiated to perform a copy). The footnote reads
"Template constructors participate in overload resolution with other
constructors, including copy constructors, and a template constructor may be
used to copy an object if it provides a better match than other
constructors.".

I sent a question some time ago about this paragraph to comp.std.c++, but it
was lost somehow in the moderation queue, i think. It was about the precise
meaning of "is never instantiated to perform the copy". It does not really
say that the constructor template is ignored, in my opinion. For instance,
what happens if you instantiate it using an explicit instantiation, or if
you explicitly specialize it? Does it use the constructor but relies on a
specialization elsewhere, or does it just not consider the constructor as a
candidate? I don't feel like the paragraph is sufficiently clear about these
issues.

But i nontheless think the intent is that it says the constructor is not
considered, and that it only applies to cases that violate the rule directly
preceeding it (non-reference parameter).

> I slightly modified your example, declaring A's constructor template
> "explicit", and replacing the direct-initialization of b2 by
> copy-initialization:
>
>    //////////////////////////////////////////////////
>    #include <iostream>
>    #include <memory>
>    using namespace std;
>
>    struct A {
>      A() {}
>      template<typename T> explicit A(T&) {
>        cout << "Explicit constructor template!" << endl;
>      }
>    };
>
>    struct B : A { auto_ptr<int> p; };
>
>    int main() {
>      B b1;
>      B b2 = b1;
>    }
>    //////////////////////////////////////////////////
>
> To my surprise, the implicit copy-constructor of B kept calling A's
> constructor template, at least on GCC 4.1.2: http://codepad.org/YB4AlSRQ
>
The kind of initialization does not dictate the kind of initialization used
for bases and members. It's not inheriting to those contexts. Issue #535
does not estabish such a thing either.

> Personally I don't feel very comfortable about implicit copy-constructors
> calling non-copy constructors. I'd be even more concerned if implicit
> copy-constructors might call explicit (non-converting) constructors, as in
> the example above. Does anybody share my concerns with respect to CWG
> #535?
>

Since there is only one implicit copy constructor definition, i'm not sure
whether it is possible to make the kind of initialization depend on the
context of direct/copy initialization (which might happen in a different
translation unit). For reference binding, for instance, this is different,
and list initialization *will* make a difference:

struct A { explicit A(int); };

// valid - "A" temporary direct initialized
A const& a{1};

// invalid - "A" temporary copy initialized.
A const& a(1);

Whether this is good or not - i'm not sure :) Making the difference for
implicit copy constructor would require tweaking the ODR - and this would
still leave the case open what happens if the same TU would make both a copy
and a direct initialization (will there be two implicit definitions?). The
ODR currently says (n3000):

"if D is a class with an implicitly-declared constructor (12.1), it is as if
the constructor was implicitly defined in every translation unit where it is
used, and the implicit definition in every translation unit shall call the
same constructor for a base class or a class member of D."


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: eldiener <eldiener@tropicsoft.com>
Date: Thu, 31 Dec 2009 01:17:02 CST
Raw View
If I have a templated constructor in a base class, such as:

struct Base
{
template<class U> Base(U arg) { }
};

does the templated constructor get called rather than the compiler-
generated copy constructor from a derived class's compiler-generated
copy constructor, such as:

struct Derived : Base
{
};

?

I was told, by a Microsoft VC++ employee responding to my bug report,
that the compiler-generated copy constructor of the Derived class
finds the templated constructor of the Base class a better match than
the compiler-generated copy constructor of the Base class. Furthermore
that since the templated constructor gets called, this causes an
infinite recursion when copying a Derived class object, such as:

Derived a;
Derived b(a);

because the compiler-generated copy constructor of the Derived class
must again be called to convert the 'const Derived &' parameter to the
U arg of the called Base class's templated constructor etc. This is
certainly an unwelcome result of compiler-generated copy constructors
in this case and most unexpected.

Is this the way that the standard is interpreted or does the compiler-
generated constructor of the Derived class call the compiler-generated
constructor of the Base class instead of the templated base class
constructor ?

I know the workaround is to manually supply the copy constructor for
Derived to call the compiler-generated copy constructor of base, such
as:

struct Derived : Base
{
Derived(const Derived & arg) : Base(static_cast<const Base &>(arg))
{ }
};

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Thomas Maeder <maeder@glue.ch>
Date: Thu, 31 Dec 2009 09:27:06 CST
Raw View
eldiener <eldiener@tropicsoft.com> writes:

> If I have a templated constructor in a base class, such as:
>
> struct Base
> {
> template<class U> Base(U arg) { }
> };
>
> does the templated constructor get called rather than the compiler-
> generated copy constructor from a derived class's compiler-generated
> copy constructor, such as:
>
> struct Derived : Base
> {
> };
>
> ?

The generated Base copy constructor is invoked.


> I was told, by a Microsoft VC++ employee responding to my bug
> report, that the compiler-generated copy constructor of the Derived
> class finds the templated constructor of the Base class a better
> match than the compiler-generated copy constructor of the Base
> class.

This is not correct.


> Furthermore that since the templated constructor gets called,
> this causes an infinite recursion when copying a Derived class
> object, such as:
>
> Derived a;

[Unrelated: your classes lack the necessary default constructors.]


> Derived b(a);
>
> because the compiler-generated copy constructor of the Derived class
> must again be called to convert the 'const Derived &' parameter to the
> U arg of the called Base class's templated constructor etc. This is
> certainly an unwelcome result of compiler-generated copy constructors
> in this case and most unexpected.

In don't see where this infinite recursion could happen.


> Is this the way that the standard is interpreted or does the
> compiler- generated constructor of the Derived class call the
> compiler-generated constructor of the Base class instead of the
> templated base class constructor ?

See above.


> I know the workaround is to manually supply the copy constructor for
> Derived to call the compiler-generated copy constructor of base, such
> as:
>
> struct Derived : Base
> {
> Derived(const Derived & arg) : Base(static_cast<const Base &>(arg))
> { }
> };

This is a different situation, since the Derived copy constructor is not
generated.

In this situation, the static_cast trick is appropriate, since if
you wrote

struct Derived : Base
{
   Derived(const Derived & arg)
      : Base(arg)
   {
   }
};

, the Base constructor generated from the template (for U=Derived)
would indeed be a better match than the generated Base copy
constructor. Which would indeed result in the infinite recursion that
you are desribing above.


Are you sure that the response from Microsoft refered to the situation
where the Derived copy constructor is generated?

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: eldiener <eldiener@tropicsoft.com>
Date: Fri, 1 Jan 2010 00:47:48 CST
Raw View
On Dec 31, 10:27 am, Thomas Maeder <mae...@glue.ch> wrote:
> eldiener <eldie...@tropicsoft.com> writes:
> > If I have a templated constructor in a base class, such as:
>
> > struct Base
> > {
> > template<class U> Base(U arg) { }
> > };
>
> > does the templated constructor get called rather than the compiler-
> > generated copy constructor from a derived class's compiler-generated
> > copy constructor, such as:
>
> > struct Derived : Base
> > {
> > };
>
> > ?
>
> The generated Base copy constructor is invoked.
>
> > I was told, by a Microsoft VC++ employee responding to my bug
> > report, that the compiler-generated copy constructor of the Derived
> > class finds the templated constructor of the Base class a better
> > match than the compiler-generated copy constructor of the Base
> > class.
>
> This is not correct.

Is there a section of the C++ standard that explains this ?

>
> > Furthermore that since the templated constructor gets called,
> > this causes an infinite recursion when copying a Derived class
> > object, such as:
>
> > Derived a;
>
> [Unrelated: your classes lack the necessary default constructors.]

I meant to code a default constructor for the base and derived
classes.

>
> > Derived b(a);
>
> > because the compiler-generated copy constructor of the Derived class
> > must again be called to convert the 'const Derived &' parameter to the
> > U arg of the called Base class's templated constructor etc. This is
> > certainly an unwelcome result of compiler-generated copy constructors
> > in this case and most unexpected.
>
> In don't see where this infinite recursion could happen.
>
> > Is this the way that the standard is interpreted or does the
> > compiler- generated constructor of the Derived class call the
> > compiler-generated constructor of the Base class instead of the
> > templated base class constructor ?
>
> See above.
>
> > I know the workaround is to manually supply the copy constructor for
> > Derived to call the compiler-generated copy constructor of base, such
> > as:
>
> > struct Derived : Base
> > {
> > Derived(const Derived & arg) : Base(static_cast<const Base &>(arg))
> > { }
> > };
>
> This is a different situation, since the Derived copy constructor is not
> generated.
>
> In this situation, the static_cast trick is appropriate, since if
> you wrote
>
> struct Derived : Base
> {
>    Derived(const Derived & arg)
>       : Base(arg)
>    {
>    }
>
> };
>
> , the Base constructor generated from the template (for U=Derived)
> would indeed be a better match than the generated Base copy
> constructor. Which would indeed result in the infinite recursion that
> you are desribing above.

I understand that.

>
> Are you sure that the response from Microsoft refered to the situation
> where the Derived copy constructor is generated?

In my original example I posted code in which there was no user-
defined copy constructor in the derived class, like my much simpler
example above. The response by Microsoft was that recursion still
occurred based on the idea that the compiler-generated derived class
copy constructor called the templated base class constructor rather
than the compiler-generated base class copy constructor. The example
posted by the Microsoft employee showed a user-defined derived class
copy constructor calling the base class constructor without the
necessary static cast, thereby justifying the original Microsoft
comment even though the situations were obviously different. My
attempts to straighten this out with the Microsoft respondee have not
helped, as there seems to be a rather stubborn insistence by that
person that the VC++ compiler is doing the correct thing by both
warning about recursive code and actually generating it. For the
record my original code is:

#include "StdAfx.h"

struct XX {};
struct YY {};

template <class T>
struct IInterface
{
virtual T InterfaceFunction() const = 0;
};

template <class T,
          class G = YY
          >
class AClassTemplate;

template <class T>
class AClassTemplate<T,XX> :
public IInterface<T>
{
private:
T data;
public:
T InterfaceFunction() const
     {
     return(data);
     }
AClassTemplate() {}
explicit AClassTemplate(T arg) {}
template<class U> explicit AClassTemplate(U arg) {}
};

template <class T>
struct AClassTemplate<T,YY> :
AClassTemplate<T,XX>
{
AClassTemplate() {}
explicit AClassTemplate(T arg) :
     AClassTemplate<T,XX>(arg) {}
};

struct PAutoClass
{
AClassTemplate<double> AVariable;
PAutoClass():AVariable(56.43) {}
};

struct PAutoX
{
AClassTemplate<PAutoClass> ClassProperty;
PAutoX() {}
};

void TestAClassTemplate()
{
PAutoX x;
}

In C++ I get a 'warning C4717:
'AClassTemplate<double,YY>::AClassTemplate<double,YY>' : recursive on
all control paths, function will cause runtime stack overflow'.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Niels Dekker - no reply address" <invalid@this.is.invalid>
Date: Sat, 2 Jan 2010 21:07:14 CST
Raw View
eldiener wrote:
> For the record my original code is:
>
> #include "StdAfx.h"
>
> struct XX {};
> struct YY {};
>
> template <class T>
> struct IInterface
> {
> virtual T InterfaceFunction() const = 0;
> };
>
> template <class T,
>          class G = YY
>          >
> class AClassTemplate;
>
> template <class T>
> class AClassTemplate<T,XX> :
> public IInterface<T>
> {
> private:
> T data;
> public:
> T InterfaceFunction() const
>     {
>     return(data);
>     }
> AClassTemplate() {}
> explicit AClassTemplate(T arg) {}
> template<class U> explicit AClassTemplate(U arg) {}
> };
>
> template <class T>
> struct AClassTemplate<T,YY> :
> AClassTemplate<T,XX>
> {
> AClassTemplate() {}
> explicit AClassTemplate(T arg) :
>     AClassTemplate<T,XX>(arg) {}
> };
>
> struct PAutoClass
> {
> AClassTemplate<double> AVariable;
> PAutoClass():AVariable(56.43) {}
> };
>
> struct PAutoX
> {
> AClassTemplate<PAutoClass> ClassProperty;
> PAutoX() {}
> };
>
> void TestAClassTemplate()
> {
> PAutoX x;
> }
>
> In C++ I get a 'warning C4717:
> 'AClassTemplate<double,YY>::AClassTemplate<double,YY>' : recursive on
> all control paths, function will cause runtime stack overflow'.

For the record, your bug report is publicly available  :-)
Title: "warning C4717 'recursive on all control paths error' erroneous"
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=522094

And yes, I'm able to reproduce the issue.

Kind regards,

 Niels
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]