Topic: Which parameter declaration wins?


Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 2000/09/25
Raw View
Niels Dekker <ndekker@REMOVETHISnki.nl> writes:

>It seems like Borland has its own (non-Standard) interpretation of const
>parameters.  Have you tried to compile something like the following?
>
>  void NullifyArray(const int arr[])
>  {
>    arr = 0;
>  }
>
>Borland C++ (up to 5.5.1) rejects the function, saying:
>  Cannot modify a const object in function NullifyArray(const int * const)
>
>Actually I'm very happy with this compiler error, because my NullifyArray
>function is buggy anyway!  :-)
>
>Personally I like using the square brackets for pointer-to-array parameters.
>But I would have liked it even more if C++ would offer me a way to declare
>such a pointer parameter as const, while still using the square brackets.
>Shouldn't the following use of the const keyword be added to the Standard???
>  void MyFunc(int arr const [])
>  {
>    // Should prevent assignments to arr!
>  }

The C99 standard (6.7.5.2, 6.7.5.3) allows the following syntax:

 void foo(int const arr[const]);

Any cv-qualifiers inside the brackets apply to the pointer parameter.

This might well make it into the next C++ standard.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3        |     -- the last words of T. S. Garp.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: comeau@panix.com (Greg Comeau)
Date: 2000/09/25
Raw View
In article <MPG.143420bf759bbd30989741@news.supernews.com>,
Scott Meyers  <smeyers@aristeia.com> wrote:
>On Thu, 21 Sep 2000 14:29:04 CST, Greg Comeau wrote:
>> Even if it was supposed to create a composite type, how could
>> case 1 by ok?  Unless that compiler only picks up the first one.
>> What does it do with:
>> void f(const int); void f(int); void f(const int x) { x = 0; } ?
>
>It rejects it.  If you omit the first declaration for f, it accepts it.
>And because I like to point fingers and hopefully embarrass vendors into
>fixing things, "it" is Borland C++ 5.5.1, the latest freely downloadable
>version of their compiler.

I have no problem with folks naming names, it's simply part of
the information IMO, but it really seems unnecessary to feel
the need to purposely embarrass.  Anyway, it's odd it works that way.

- Greg
--
Comeau Computing / Comeau C/C++ ("so close" 4.2.44 betas starting)
TRY Comeau C++ ONLINE at http://www.comeaucomputing.com/tryitout
Email: comeau@comeaucomputing.com / WEB: http://www.comeaucomputing.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: ivec@surgnav.com (Ivan Vecerina)
Date: 2000/09/25
Raw View
Scott Meyers said:
>But consider what happen when the second declaration is also a definition:
>
>  void f(int x);           // case 1:  x is declared non-const in f's
>  void f(const int x)      //          declaration and const in its defn
>  {
>    x = 0;                 // modify x
>  }

This must fail because x is constant within the implementation of f(int).

>  void f(const int x);     // case 2:  x is declared const in f's
>  void f(int x)            //          declaration and non-const in its defn
>  {
>    x = 0;                 // modify x
>  }

This is ok, as a top-most const of a by-value parameter is to be
disregarded in the function's declaration.
However, it is a bad coding practice to put that const in the
function's declaration, as it is not part of the function's interface.

>Most of my compilers reject case 1 and accept case 2, but one does the
>reverse.  Which is correct, and why?

It is not a matter of win or lose. In my perspective, the correct
usage of that const is very clear based on what the standard defines:

The top-most const of a by-value parameter applies to the
copy of the value that is received by the function.
It is therefore **not part of the function's interface**, and should
never be present in a function's declaration.

Because, obviously, the following calls shall all work in either case:
  int i = 3;
  f(i);
  f(5); // non-const copy of const parameter is passed to f( int );
  const int j = i;
  f(j); // another try: again, the function receives a copy of j
Who cares if the copy received by the function is const or not ?
So:
GOOD: void f(int x);
BAD:  void f(const int x); // declares the same function
 is not an error, but could/should trigger a compiler warning.

 NB: would anyone dare suggest that all by-value parameters should
     be declared as const in a function's declaration ?  8]


Now given a function whose interface is "void f(int)", a top-level
const can be added to the parameter in the function's definition.
It is used to specify that the parameter (the copy of the parameter
that the function received) shall remain constant within the function:

A possible implementation:
 void f(int x)
 {
   ++x;
   cout << x;
 }

Another possible implementation:
 void f(const int x)
 {
   .... // dozens of lines
   // ++x would be a compiler error
   .... // dozens of lines

   cout << x;  // without reading the previous code, I can be
               // sure that the value of x is still the same
               // as the one that was passed initially: it is const.
 }

Basically, that optional const is an implementation detail.
A by-value parameter is like a local variable - you can choose to
have it const or not. In either case, it is an implementation detail
and not part of the function's interface.

Further examples:

  Reference:

Of course:  void g(int& x)            // A
or:         void g(const int& x)      // B
are clearly different functions ...
  g(5); // will only work if G is declared as in B.


  Pointer:

  void h(  /*const1*/  int*  /*const2*/  x  );
The second const is the one I call the top-level const of a by-value
parameter.
Given the declaration:
  void h( int* x ); // h modifies value pointed to by parameter x
Possible implementation
  void h( int* const x ) // value of the pointer will not change
  {
    //++p;   -- would be a compiler error
    *p = 0;  // sets contents of pointer
  }
But the following would define a different function:
  void h( const int* x );
    // not the top-level const... changes h's interface.


Etc...


I feel I have been explaining this const parameter thing
dozens of times to coworkers or on mailing lists/NGs.
IMHO, every C++ book which recommends the use of const
variables should explain that usage too ;)

Regards,
  Ivan

---------------------------------------------------------
 Ivan Vecerina, Dr. med.
 Senior Software Developer - Surgical Navigation Network
  <http://www.surgnav.com> - <http://www.cedara.com>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Scott Meyers <smeyers@aristeia.com>
Date: 2000/09/22
Raw View
On Thu, 21 Sep 2000 14:29:04 CST, Greg Comeau wrote:
> Even if it was supposed to create a composite type, how could
> case 1 by ok?  Unless that compiler only picks up the first one.
> What does it do with:
> void f(const int); void f(int); void f(const int x) { x = 0; } ?

It rejects it.  If you omit the first declaration for f, it accepts it.
And because I like to point fingers and hopefully embarrass vendors into
fixing things, "it" is Borland C++ 5.5.1, the latest freely downloadable
version of their compiler.

> BTW, we debated this years ago when you spoke to the C++ SIG in NYC!! :)

It seems I have either a bad memory or I'm a *really* slow learner :-)

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 2000/09/22
Raw View
Scott Meyers wrote:
>
> On Thu, 21 Sep 2000 14:29:04 CST, Greg Comeau wrote:
> > What does it do with:
> > void f(const int); void f(int); void f(const int x) { x = 0; } ?
>
> It rejects it.  If you omit the first declaration for f, it accepts it.
> And because I like to point fingers and hopefully embarrass vendors into
> fixing things, "it" is Borland C++ 5.5.1, the latest freely downloadable
> version of their compiler.

It seems like Borland has its own (non-Standard) interpretation of const
parameters.  Have you tried to compile something like the following?

  void NullifyArray(const int arr[])
  {
    arr = 0;
  }

Borland C++ (up to 5.5.1) rejects the function, saying:
  Cannot modify a const object in function NullifyArray(const int * const)

Actually I'm very happy with this compiler error, because my NullifyArray
function is buggy anyway!  :-)

Personally I like using the square brackets for pointer-to-array parameters.
But I would have liked it even more if C++ would offer me a way to declare
such a pointer parameter as const, while still using the square brackets.
Shouldn't the following use of the const keyword be added to the Standard???
  void MyFunc(int arr const [])
  {
    // Should prevent assignments to arr!
  }


Have a nice weekend,

  Niels Dekker
  ndekker "at" nki "dot" nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Scott Meyers <smeyers@aristeia.com>
Date: 2000/09/21
Raw View
8.3.5/3 makes clear that the following declares the same function twice:

  void f(int x);
  void f(const int x);     // same function -- the const is ignored

Obviously, then, it doesn't matter what order you put the declarations in:

  void f(const int x);     // still the same function declared twice
  void f(int x);

But consider what happen when the second declaration is also a definition:

  void f(int x);           // case 1:  x is declared non-const in f's
  void f(const int x)      //          declaration and const in its defn
  {
    x = 0;                 // modify x
  }

  void f(const int x);     // case 2:  x is declared const in f's
  void f(int x)            //          declaration and non-const in its defn
  {
    x = 0;                 // modify x
  }

Most of my compilers reject case 1 and accept case 2, but one does the
reverse.  Which is correct, and why?

Thanks,

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: wmm@fastdial.net
Date: 2000/09/21
Raw View
In article <MPG.1432e878a09d754e989740@news.supernews.com>,
  Scott Meyers <smeyers@aristeia.com> wrote:
> 8.3.5/3 makes clear that the following declares the same function
twice:
>
>   void f(int x);
>   void f(const int x);     // same function -- the const is ignored
>
> Obviously, then, it doesn't matter what order you put the
declarations in:
>
>   void f(const int x);     // still the same function declared twice
>   void f(int x);
>
> But consider what happen when the second declaration is also a
definition:
>
>   void f(int x);           // case 1:  x is declared non-const in f's
>   void f(const int x)      //          declaration and const in its
defn
>   {
>     x = 0;                 // modify x
>   }
>
>   void f(const int x);     // case 2:  x is declared const in f's
>   void f(int x)            //          declaration and non-const in
its defn
>   {
>     x = 0;                 // modify x
>   }
>
> Most of my compilers reject case 1 and accept case 2, but one does the
> reverse.  Which is correct, and why?

Case 1 is ill-formed, case 2 is correct.  8.3.5p3 says, "Any
cv-qualifier modifying a parameter type is deleted [in
determining the type of the function]...  Such cv-qualifiers
affect only the definition of the parameter within the body
of the function..."

Think of it this way: when you see a reference to "x" in the
body of the function, you have to do a lookup to find the
declaration.  The declaration you find is the one in the
parameter list of the function definition.  In case 1, that
declaration declares "x" to be const, so it can't be modified
in the body of the function.  In case 2, the declaration is
not const-qualified, so the assignment is permissible.

In case 2, it's the non-definition declaration that has the
const.  Such a declaration only has the effect of associating
the name and the type, and top-level cv-qualifiers are
ignored in determining the type.  Thus when you see the
definition of "f", the type that was previously declared is
"function taking int and returning void" -- the fact that the
parameter was declared const is completely forgotten and can't
have any impact at all on the definition.

--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: comeau@panix.com (Greg Comeau)
Date: 2000/09/21
Raw View
In article <MPG.1432e878a09d754e989740@news.supernews.com>,
Scott Meyers  <smeyers@aristeia.com> wrote:
>8.3.5/3 makes clear that the following declares the same function twice:
>  void f(int x);
>  void f(const int x);     // same function -- the const is ignored

Right, since it's only a prototype, the const is dropped.

>Obviously, then, it doesn't matter what order you put the declarations in:
>
>  void f(const int x);     // still the same function declared twice
>  void f(int x);

Right, it's still only a prototype, so the const is dropped.

>But consider what happen when the second declaration is also a definition:
>
>  void f(int x);  // AA    // case 1:  x is declared non-const in f's
>  void f(const int x) // BB//          declaration and const in its defn
>  {
>    x = 0;                 // modify x
>  }

AA if f(int), but BB is f(const int) so x = 0 is an error

>  void f(const int x);// CC// case 2:  x is declared const in f's
>  void f(int x) // DD      //          declaration and non-const in its defn
>  {
>    x = 0;                 // modify x
>  }

CC is f(int), and so is DD, so x = 0 is fine.

>Most of my compilers reject case 1 and accept case 2, but one does the
>reverse.  Which is correct, and why?

Even if it was supposed to create a composite type, how could
case 1 by ok?  Unless that compiler only picks up the first one.
What does it do with:
void f(const int); void f(int); void f(const int x) { x = 0; } ?

BTW, we debated this years ago when you spoke to the C++ SIG in NYC!! :)

- Greg
--
Comeau Computing / Comeau C/C++ ("so close" 4.2.44 betas starting)
TRY Comeau C++ ONLINE at http://www.comeaucomputing.com/tryitout
Email: comeau@comeaucomputing.com / WEB: http://www.comeaucomputing.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]