Topic: one definition rule
Author: steve@taumet.com (Steve Clamage)
Date: Fri, 26 Feb 1993 22:08:38 GMT Raw View
warwick@cs.uq.oz.au (Warwick Allison) writes:
>bs@alice.att.com (Bjarne Stroustrup) writes:
>>There can be many such declarations with different
>>default arguments as long as they are in different scopes. A default
>>argument does not affect the type of a function, it simply defines a
>>shorthand notation for a call.
>Hmm, maybe that explains why G++ accepts:
>class foo {
>public:
> foo(foo* n) : next(n), num(1) { }
> foo(foo* n, int i=3) : next(n), num(i) { }
>...
No it doesn't. What Bjarne was explaining is that these:
int foo(int = 2);
int foo(int = 22);
may appear in different scopes without being considered different
functions or violating the ODR. They cannot appear in the same scope.
The case you cite is an error, at least in the sense of being a mistake.
There is no way to invoke foo::foo(foo*), and the compiler must report
ambiguity when a foo constructor is invoked with only a foo* argument.
It is not clear to me that the compiler must report a declaration error,
although some compilers do.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: steve@taumet.com (Steve Clamage)
Date: Wed, 17 Feb 1993 18:42:42 GMT Raw View
adk@Warren.MENTORG.COM (Ajay Kamdar) writes:
>Is the "one definition" rule explicitly stated in the ARM? I couldn't find it;
>I would much appreciate a reference to it.
Page 14: "There must be exactly one definition of each object, function,
class, and enumerator used in a program."
>I have here an example of member functions with default arguments.
>Does it violate the one definition rule?
>=== a.h ===
>class A {
>public:
>#ifdef DEFX
> int f(int arg=0);
>#else
> int f(int arg=1);
>#endif
> // default argument to f() depends upon whether DEFX is defined.
>};
I don't think it violates the rule (the default value is not part of
the class or the type of the function or the function definition)
but there is room for other opinions.
I do think it is a bad programming practice, particularly when
different parts of the program are compiled with different default
parameters for A::f().
I suggest defining a local constant or variable in each module
which is then used as the explicit parameter to A::f().
#include "a.h"
#ifdef DEFX
const int default = 0;
#else
const int default = 1;
#endif
// now we call A::f()
A a;
a.f(default);
Now there is no multiple definition for anything. Each module can
be compiled with either 0 or 1 as the default parameter to A::f().
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: dak@messua.informatik.rwth-aachen.de (David Kastrup)
Date: 18 Feb 93 14:18:50 GMT Raw View
steve@taumet.com (Steve Clamage) writes:
>adk@Warren.MENTORG.COM (Ajay Kamdar) writes:
>>I have here an example of member functions with default arguments.
>>Does it violate the one definition rule?
>>=== a.h ===
>>class A {
>>public:
>>#ifdef DEFX
>> int f(int arg=0);
>>#else
>> int f(int arg=1);
>>#endif
>> // default argument to f() depends upon whether DEFX is defined.
>>};
>I don't think it violates the rule (the default value is not part of
>the class or the type of the function or the function definition)
>but there is room for other opinions.
Rubbish. It does not violate the rule because the compiler gets to
see only one definition. The preprocessor filters out the other
one before. However, compiling separately, once with DEFX, once
without, will be erroneous because of conflicting definitions
for int f().
--
David Kastrup dak@messua.informatik.rwth-aachen.de
Tel: +49-241-72419 Fax: +49-241-79502
Goethestr. 20, W-5100 Aachen, Germany
Author: steve@taumet.com (Steve Clamage)
Date: Sat, 20 Feb 1993 21:15:55 GMT Raw View
dak@messua.informatik.rwth-aachen.de (David Kastrup) writes:
>Rubbish. It does not violate the rule because the compiler gets to
>see only one definition. The preprocessor filters out the other
>one before. However, compiling separately, once with DEFX, once
>without, will be erroneous because of conflicting definitions
>for int f().
The question involved using conditional code to change the default
parameters on a function, with the proviso that different modules
would use different parts of the conditional code.
The ODR says that a type, object, or function must have exactly one
definition in the entire program. Using conditional code per se
does not violate the rule. Using different macro settings to get
different definitions in different modules for the same object
does violate the ODR. For example:
// common header file
#ifdef FOO
class A { int x; ... };
#else
class A { double x; ... };
#endif
If the entire program is compiled with FOO either defined or undefined,
there is no violation of the ODR. If one module is compiled with
FOO defined and another in the same program with FOO undefined, that
does violate the ODR.
The original example did not violate the ODR only because no definition
of any type or object was affected by the conditional code.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
Author: warwick@cs.uq.oz.au (Warwick Allison)
Date: 24 Feb 93 05:15:04 GMT Raw View
bs@alice.att.com (Bjarne Stroustrup) writes:
>default arguments apply where the function declaration they are
>part of is in scope. There can be many such declarations with different
>default arguments as long as they are in different scopes. A default
>argument does not affect the type of a function, it simply defines a
>shorthand notation for a call.
Hmm, maybe that explains why G++ accepts:
class foo {
public:
foo(foo* n) : next(n), num(1) { }
foo(foo* n, int i=3) : next(n), num(i) { }
private:
foo* next;
int num;
};
*Groan* I hate that. OBVIOUSLY the class designer has made an error, but
it is not flagged. Not even warned when put up against the -Wall.
--
Warwick
_-_|\ warwick@cs.uq.oz.au /Disclaimer:
/ * <-- Computer Science Department, /
\_.-._/ University of Queensland, / C references are NULL && void*
v Brisbane, Australia. /
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 24 Feb 93 14:26:15 GMT Raw View
From: warwick@cs.uq.oz.au (Warwick Allison) writes
> bs@alice.att.com (Bjarne Stroustrup) writes:
>
> >default arguments apply where the function declaration they are
> >part of is in scope. There can be many such declarations with different
> >default arguments as long as they are in different scopes. A default
> >argument does not affect the type of a function, it simply defines a
> >shorthand notation for a call.
>
> Hmm, maybe that explains why G++ accepts:
>
> class foo {
> public:
> foo(foo* n) : next(n), num(1) { }
> foo(foo* n, int i=3) : next(n), num(i) { }
>
> private:
> foo* next;
> int num;
> };
>
>
> *Groan* I hate that. OBVIOUSLY the class designer has made an error, but
> it is not flagged. Not even warned when put up against the -Wall.
It is a question of where an error is detected. In general C++ truies not to
give fail programs for having potential errors, it waits until an error is
actually made. In this case the declaration of class foo is accepted and also
the unambiguous use
foo a(1,2);
but if you try to ambiguous
foo a(1);
the compiler complains.
In this case, one could argue that we could just as well have given the error
when we saw the class declaration, but I have seen reasonable uses of global
functions defined equivalently. The one argument version was the original, the
two argument version an alternative. The two declarations lived in different
header files. The intent was to move to the two argument version, but the
transition took time.
- Bjarne
Author: adk@Warren.MENTORG.COM (Ajay Kamdar)
Date: 15 Feb 1993 13:18:12 -0500 Raw View
Is the "one definition" rule explicitly stated in the ARM? I couldn't find it;
I would much appreciate a reference to it.
I have here an example of member functions with default arguments.
Does it violate the one definition rule?
=== a.h ===
class A {
public:
#ifdef DEFX
int f(int arg=0);
#else
int f(int arg=1);
#endif
// default argument to f() depends upon whether DEFX is defined.
};
=== b.c ====
#define DEFX
#include "a.h"
//....
A a;
a.f(); // argument defaults to 0
=== c.c ===
#include "a.h" // DEFX not defined
//....
A aa;
aa.f(); // argument defaults to 1
8.2.6 (pg. 143) says "A default argument is not part of the type of a
function." Hence the signature of A::f is the same whether DEFX is defined
or not. Hence the definition of class A in both b.c and c.c is the same.
Is this sufficient to satisfy the one definition rule?
Thanks.
- Ajay
--
I speak for none but myself.
Ajay Kamdar Email : ajay_kamdar@mentorg.com
Mentor Graphics, IC Group (Warren, NJ) Phone : (908) 604-0842
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 17 Feb 93 01:32:10 GMT Raw View
adk@Warren.MENTORG.COM (Ajay Kamdar @ Mentor Graphics Corp. -- IC Group) writes
> Is the "one definition" rule explicitly stated in the ARM? I couldn't find it;
> I would much appreciate a reference to it.
Section 3.3 (top of page 18 in the ARM)
> I have here an example of member functions with default arguments.
> Does it violate the one definition rule?
No. default arguments apply where the function declaration they are
part of is in scope. There can be many such declarations with different
default arguments as long as they are in different scopes. A default
argument does not affect the type of a function, it simply defines a
shorthand notation for a call.