Function returns and explicit construction

Function returns and explicit construction

Post by Jim Melto » Fri, 01 Aug 2003 21:36:48



I have been bitten a couple of times by implicit type conversions, and so
had to retrofit about 50 classes to use the explicit keyword for
constructors. But we just recently got bitten in spite of the explicit
keyword. Does the "return" statement qualify as explicit construction?

Consider:

class ABaseClass {};
template<class Type, class Uncert>
class Value
{
public:
     Value(Type const& t, Uncert const& u) : _t(t), _u(u) {}
protected:
     Type       _t;
     Uncert    _u;

class Foo : public Value<float, double>, public ABaseClass
{
public:
     explicit
     Foo(ABaseClass b=ABaseClass(), float val=-1, double tol=0)
         : ABaseClass(b), Value(val, tol)
     {
         std::cerr << "Explicit constructed Foo\n";
     }

Quote:};

class Bar : public Value<int, double>, public ABaseClass
{
public:
     explicit
     Bar(ABaseClass b=ABaseClass(), int val=-1, double tol=0)
         : ABaseClass(b), Value(val, tol)
     {
         std::cerr << "Explicit constructed Bar\n";
     }

Quote:};

class Context
{
public:
     Context() : _foo(ABaseClass(), 1.23, 0.45) {}
     Bar getFoo() const
     {
         return _foo;
     }
private:
     Foo _foo;

Quote:};

int main()
{
     Context c;
     c.getFoo();

Quote:}

Note that Context::getFoo has a type mismatch between the declared return
type and the return value. This was a bug that was not caught by the
compiler. Intstead, Bar(static_cast<ABaseClass>(_foo)) is invoked and
returned. The output of this run is:

Explicit constructed Foo   (Context constructor)
Explicit constructed Bar    (Context::getFoo return)

Is this what I should expect? Does the language offer me any hope in
preventing these kinds of errors from seeing the light of day?
--
<disclaimer>
Opinions posted are those of the author.
My company doesn't pay me enough to speak for them.
</disclaimer>
--
Jim Melton
Software Architect, Fusion Programs
Lockheed Martin Astronautics
(303) 971-3846

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

Function returns and explicit construction

Post by Ben Hutching » Sat, 02 Aug 2003 04:10:56



> I have been bitten a couple of times by implicit type conversions, and so
> had to retrofit about 50 classes to use the explicit keyword for
> constructors. But we just recently got bitten in spite of the explicit
> keyword. Does the "return" statement qualify as explicit construction?

No, it doesn't.

<snip>

Quote:> Note that Context::getFoo has a type mismatch between the declared return
> type and the return value. This was a bug that was not caught by the
> compiler.

<snip>

That would be a compiler bug, then.  For the record, g++ 3.0, VC++ 7.0 and
Comeau C++ 4.3.1 all report an error in the return statement.

g++ and VC++ also require that the initialiser lists for Foo and Bar
include template arguments for Value, but Comeau doesn't.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

Function returns and explicit construction

Post by llewell » Sat, 02 Aug 2003 09:44:24



> I have been bitten a couple of times by implicit type conversions, and so
> had to retrofit about 50 classes to use the explicit keyword for
> constructors. But we just recently got bitten in spite of the explicit
> keyword. Does the "return" statement qualify as explicit construction?

> Consider:

> class ABaseClass {};
> template<class Type, class Uncert>
> class Value
> {
> public:
>      Value(Type const& t, Uncert const& u) : _t(t), _u(u) {}
> protected:
>      Type       _t;
>      Uncert    _u;

  };

Quote:

> class Foo : public Value<float, double>, public ABaseClass
> {
> public:
>      explicit
>      Foo(ABaseClass b=ABaseClass(), float val=-1, double tol=0)
>          : ABaseClass(b), Value(val, tol)

         : Value<float,double>(val, tol), ABaseClass(b)

Quote:>      {
>          std::cerr << "Explicit constructed Foo\n";
>      }
> };

> class Bar : public Value<int, double>, public ABaseClass
> {
> public:
>      explicit
>      Bar(ABaseClass b=ABaseClass(), int val=-1, double tol=0)
>          : ABaseClass(b), Value(val, tol)

           : Value<int,double>(val, tol), ABaseClass(b)

Quote:>      {
>          std::cerr << "Explicit constructed Bar\n";
>      }
> };

> class Context
> {
> public:
>      Context() : _foo(ABaseClass(), 1.23, 0.45) {}
>      Bar getFoo() const
>      {
>          return _foo;

After correcting the above errors, this line results in:

g++ -g -W -Wall jim.cc
jim.cc: In member function `Bar Context::getFoo() const':
jim.cc:44: error: conversion from `const Foo' to non-scalar type `Bar'
   requested

which I believe to be consistent with 12.3.1/2 .  

Quote:>      }
> private:
>      Foo _foo;
> };

> int main()
> {
>      Context c;
>      c.getFoo();
> }

> Note that Context::getFoo has a type mismatch between the declared return
> type and the return value. This was a bug that was not caught by the
> compiler.

If your compiler doesn't emit a diagnostic you should report a bug to
    the implementor (but hopefully with better code than the above. :-)

[snip]

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

Function returns and explicit construction

Post by John Potte » Sat, 02 Aug 2003 09:45:26



Quote:> I have been bitten a couple of times by implicit type conversions, and so
> had to retrofit about 50 classes to use the explicit keyword for
> constructors. But we just recently got bitten in spite of the explicit
> keyword. Does the "return" statement qualify as explicit construction?

No.

Quote:> class ABaseClass {};
> template<class Type, class Uncert>
> class Value
> {
> public:
>      Value(Type const& t, Uncert const& u) : _t(t), _u(u) {}
> protected:
>      Type       _t;
>      Uncert    _u;
};  // oops
> class Foo : public Value<float, double>, public ABaseClass
> {
> public:
>      explicit
>      Foo(ABaseClass b=ABaseClass(), float val=-1, double tol=0)
>          : ABaseClass(b), Value(val, tol)

Gcc demanded Value<float, double> here and in Bar.

Quote:>      Bar getFoo() const
>      {
>          return _foo;
>      }

Gcc:
In member function `Bar Context::getFoo() const':
conversion from `const Foo' to non-scalar type `Bar' requested

Comeau online:
"ComeauTest.c", line 32: error: no suitable user-defined conversion from
"const Foo" to "Bar" exists
           return _foo;
                  ^

Quote:> Does the language offer me any hope in
> preventing these kinds of errors from seeing the light of day?

Looks like time for either an upgrade or bug report on your compiler.

It might also help to just try some other compilers.  C++ is still
not at the point where one is enough to catch all errors.

John

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

Function returns and explicit construction

Post by Richard Smit » Sat, 02 Aug 2003 09:53:36



> class ABaseClass {};
> template<class Type, class Uncert>
> class Value
> {
> public:
>      Value(Type const& t, Uncert const& u) : _t(t), _u(u) {}
> protected:
>      Type       _t;
>      Uncert    _u;

You're missing a close brace here, but I'm sure that's just
an error copying the code into the post.

Quote:> class Foo : public Value<float, double>, public ABaseClass
> {
> public:
>      explicit
>      Foo(ABaseClass b=ABaseClass(), float val=-1, double tol=0)
>          : ABaseClass(b), Value(val, tol)

The base classes are initialised in the wrong order; also,
Value must be initialised as Value<float,double>(val,tol).

Quote:> class Context
> {
> public:
>      Context() : _foo(ABaseClass(), 1.23, 0.45) {}
>      Bar getFoo() const
>      {
>          return _foo;
>      }

There's absolutely no doubt that this is illegal.  _foo is
of type Foo, the return value is of type Bar, and there are
no implicit conversions between the two types.  If your
compiler accepts this code, I'd be worried.  I've tried a
the code in a number of compilers, including some
pre-Standard ones, and they all reject this line.

--
Richard Smith

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

1. explicit construction in function return

The way I interpret the standard, the following code

   struct H
   {
      explicit H (int i) : myi (i) {}
      int myi;
   };

   H f ()
   {
      static int i;
      return i;
   }

   int main ()
   {
      H h = f ();
      return 0;
   }

should be ill-formed because

"An explicit constructor constructs objects just like non-explicit
constructors, but does so only when the direct initialization syntax
(8.5) or where casts (5.2.9, 5.4) are explicitly used." (12.3.1/2)

and

"The initialization that occurs in new-expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and
base and member initializers (12.6.2) is called direct-initialization"
(8.5)

In the same clause, function return, which is what happens in the code
above, is listed under copy-initialization. Nevertheless, both compilers
I am using accept the code. Am I missing something?

Gerhard Menzl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

2. IE 4 and Beta 5 Cookies

3. Placement Construction and Explicit Destruction

4. Static Members and Static Member Pointers

5. Explicit template parameters on construction

6. Install Problem

7. proposal: explicit return types

8. cxxlink problems with JNI_CreateJavaVM

9. confused about 'explicit' copy-constructor and 'return'

10. explicit and conversion during return

11. function to return count doesn't return correct count

12. Preventing temporary object construction in function call

13. STL function object construction problem