Topic: Some ideas about C++ and a question
Author: A.Main@dcs.warwick.ac.uk (Zefram)
Date: 1996/03/07 Raw View
Valentin Bonnard <bonnardv@pratique.fr> wrote:
>1) String literals
>~~~~~~~~~~~~~~~~~~
>String literals should be const char* instead of char* (if it is not
>already the case).
Actually they're char[], which in practice is almost always decayed to
char*. The reason they aren't char const[] is that a lot of existing C
code does things like `char *foo="bar";', because const didn't exist in
K&R C.
In my opinion, C++ code tends to use const correctly much more than C
code does. (I personally always write const correctness into my C
code, but a lot of people do not, quite apart from the matter of
existing code.) It would therefore probably not be disastrous to have
string literals have type char const[] in C++, though it would be in
C. Maybe in the next round of standardisation?
>2) Placement operators
>~~~~~~~~~~~~~~~~~~~~~~
>class Object {
> void operator+ // or / or whatever
> (Object& result, const Object& b) const;
> void operator* (Object& result) const;
> Object operator* (const Object& result) const; // old one
>}
>
>should be called respectively by:
>a = b + c;
[...]
GCC has a better syntax for this, using a declaration "return result"
between the parameter list and the function body. The function has a
return value in the usual way, but if it doesn't contain a return
statement with a value then the object in the return declaration is
returned.
>4) Conversion of Type** to const Type**
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>It's ok, this is an error; but why cannot Type** be converted to const Type*
>const* ?
It can in C++, but not in C. It is in fact safe, but the discovery of
the problem with converting T** to T const** led to the present C rule,
which was cast in stone (figuratively) before the C++ rule was
developed.
-zefram
--
Andrew Main <zefram@dcs.warwick.ac.uk>
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: bonnardv@pratique.fr (Valentin Bonnard)
Date: 1996/03/12 Raw View
[Note: I have tried to post normally this followup, but it seam it
didn't work; this follows news:4hdctd$r1p@engnews1.Eng.Sun.COM (Steve
Clamage's article) Please remove this note before posting. ]
clamage@Eng.Sun.COM (Steve Clamage) wrote:
>Valentin Bonnard <bonnardv@pratique.fr> writes:
>
>>I have 4 ideas about C++ and a question.
>
>>1) String literals
>>~~~~~~~~~~~~~~~~~~
>>String literals should be const char* instead of char* (if it is not
>>already the case).
>
>Yes, it is clearly the "right" thing to do, but it is not the case
>for the same reason it is not the case in Standard C: it would break
>too much existing code to make the change.
Perhaps, but in C void* converted to anything* and it's not the case in C++: this broke more C code (I think, or a least more of my old C code) then what I propose.
Or could it be a compiler option (that all compilers should have) to make string literals char* ?
>>2) Placement operators
>>~~~~~~~~~~~~~~~~~~~~~~
>>class Object {
>> void operator+ // or / or whatever
>> (Object& result, const Object& b) const;
binary (compute *this + b, put the result in 'result')
>> void operator* (Object& result) const; #2
unary (compute *(*this), put the result in 'result')
>> Object operator* (const Object& result) const; // old one
^^^^^^ ops! should be named b
binary (compute *this + b, return the result)
>>}
>
>>should be called respectively by:
>>a = b + c;
>
>>and a = *b;
>
>>and (old one) a*b;
>
>>This will solve the [well-known] problem of copying the result into a temporary.
>>The compatibility will be preserved since old syntax will be allowed to.
>
>You will have to present this idea in more detail. I can't figure out
>what you are proposing. It looks like you want the function marked #2
>to be some form of unary dereferencing operator, but that would change
>its existing meaning of a member binary (multiplication) operator.
The story begin with a class Object for the construction and destruction is not trivial (and take some time):
Object a, b, c;
a = b @ c;
where @ is one of: + - * / % & | ^ && || etc... (but not one of: += -= *= /= %= &= |= ^=)
I want to be able to write (using the friend notation to make it a little more clear):
void operator @ (Object& result, const Object& a, const Object& b);
instead of
Object operator @ (const Object& a, const Object& b);
The definition would become (for example):
void operator @ (Object& result, const Object& a, const Object& b)
{
result = a;
result @= b; // direct operation
}
rather than
Object operator @ (const Object& a, const Object& b)
{
Object result = a;
result @= b;
return Object; // temporary created with copy constructor, Object deleted,
} // then temporary copied into a, and temporary deleted
The old style should still be allowed, and the operator signature is clearly distinct from the one I propose.
For unary operators, the idea is exactly the same, but it's a bit more difficult to see if it's a binary operator or a unary operator because my syntax and an argument:
(where @ is one of ! ~ unary * etc...)
Object operator @ (const Object&); // again friend version instead of member version
become
void operator @ (Object&, const Object&); // unary [2]
The problem with * is that the [2] is difficult to distinguish from
Object operator * (const Object&, const Object&); // binary *, return the result
But my operator return void, so it could be used as an indication: I don't think many people currently have code with
void operator * (Object&, const Object&); // I think this is currently legal
and who write a * b; where a will be modified !
This king of strange code would break if my proposal was accepted for unary operators, but I really don't think it is very serious.
>>3) Use of explicit keyword
>>~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>>void foo (explicit Derived* object) ...
>
>Evidently you want this to mean that "*object" is of type "Derived"
>and not of any type derived from "Derived". I guess I don't see
>the utility of the declaration. You can create a type which cannot be
>derived from, if that is what you want. If you don't want that, I
>don't see why the author of "foo" wants to be sure no derived type
>is ever passed to it. What programming problem is being solved here?
>
>The whole idea of public derivation is that a derived type can be
>used where ever a base type is expected. Why does the author of foo
>want to ensure that the actual object has, for example, no additional
>data, functionality, or instrumentation, when the author of Derived
>has no objections to the possibility?
>
>If for some reason you do care about the actual type of *object,
>wouldn't it be enough to use an RTTI expression in the function?
This could help for functions that take a Base[]:
class Base {
public:
void (*func) ();
};
class Derived {
public:
long dummy;
};
void foo_safe (explicit Base[]);
void foo_bad (Base[]);
void test ()
{
Base* der = new Derived[10];
foo_bad (der); // pass at compile time, then crash
foo_safe (der);
// the compiler will tell you 'cannot convert from Base* to explicit Base*'
}
void foo_bad (Base[] b)
{
for (int i=0; i<10; i++)
(b[i].func) (); // function call here to be sure that it crash ;->
}
void foo_safe (explicit Base[] b) // do the same thing
{
for (int i=0; i<10; i++)
(b[i].func) ();
}
I know a could use a container, but the notion of array use sometimes useful for class too.
Well, this was not the point of my idea: I wanted to the compiler to know at compile time the 'real' type of the object, not:
- use RTTI (contrary of compile time !)
- not just to protect from error (see example above)
- 'create a type which cannot be derived from', as Steve Clamage say.
(The class Derived can be derived from, since, it has a normal declaration.)
I wrote:
> object.VirtualFunc (); // nop (compiler does not generate code for this)
Since VirtualFunc is virtual, the compiler must generate code for it, even when object is a Base& and Base::VirtualFunc is defined as { } *except* if:
(a) the variable is passed by value
(b) you use explicit
(a) as obvious disadvantages in terms of speed for big classes, so the last solution is (b)...
Note: the rule for the qualifier are the *inverse* of the rules for cv (const/volatile):
~~~~~
T* -> const T* const T* !=> T*
T* -> volatile T* volatile T* !=> T*
but
explicit T* -> T* T* !=> explicit T*
where -> means can be converted to and !=> means CAN'T be converted to.
>>4) Conversion of Type** to const Type**
>>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>>It's ok, this is an error; but why cannot Type** be converted to const Type*
>>const* ?
>
>For the same reason: it could cause a violation of constness without
>a cast. The draft standard does allow Type** to be converted to
>"Type*const*", since that cannot cause any such violation.
I don't see how you could violate constness _without_ the cast; if you know, please tell me.
Valentin Bonnard
bonnardv@pratique.fr
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>
Date: 1996/03/13 Raw View
In article <v01530500ad6a43009478@[194.98.4.120]> bonnardv@pratique.fr
(Valentin Bonnard) writes:
|> clamage@Eng.Sun.COM (Steve Clamage) wrote:
|> >Valentin Bonnard <bonnardv@pratique.fr> writes:
|> >>4) Conversion of Type** to const Type**
|> >>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|> >
|> >>It's ok, this is an error; but why cannot Type** be converted to
|> >>const Type* const* ?
It can. It was banned in the C standard, and the C++ committee only
changed this rule recently, so it is possible that many compilers
don't implement it yet. (It was banned by mistake in the C standard;
the wording to forbid Type** -> Type const** was made too tight.)
|> >For the same reason: it could cause a violation of constness without
|> >a cast. The draft standard does allow Type** to be converted to
|> >"Type*const*", since that cannot cause any such violation.
|> I don't see how you could violate constness _without_ the cast; if you
|> know, please tell me.
I think Steve just misread your statement. (I know I did the first
time through.) Why you cannot convert Type** to Type const** is
almost a FAQ, and since since that was the title of point 4...
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils, itudes et rialisations en logiciel orienti objet --
-- A la recherche d'une activiti dans une region francophone
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]