Hi,
This is a question about whether I am right that a particular syntactic
sugar is missing in C++.
Let me explain with an example. Let us say I have a class for complex
numbers, and I want people to be able to initialize real numbers (like
an object of type double) from it ... in such a context (or if someone
explicitly casts to double), the imaginary part is to be ignored.
However, I certainly do not want people to be able to ask whether
Complex(1,2) > 0, or even whether Complex(1,0)>0, or pass a complex
number to a function expecting a real number. Of course, it is easy to
do that by forcing people to write definitions like `double x =
z.realpart();', but I am asking about letting people use the syntax
`double x(z)', or `double x = z'
If instead of double, I had a class Double, I could play convoluted
games with `explicit Double(Complex::Double);' and Complex::Double an
otherwise unused class (possibly by naming it
IWillBreakYourBonesIfYouUseIt) to which class Complex can be converted.
But is it really not possible to do it if I want double instead of
Double. (The rule against multiple implicit user-defined conversions and
no constructors for non-class objects seems to defeat me. If only the
rule were against more than two rather than more than one ...)
More fundamentally, is there a reason (implementation difficulty,
difficulty of specification, neatness) because of which `explicit
operator' is not in the language? Constructors and conversions work
very similarly most of the time, so why this asymmetry?
Many thanks
Tanmoy 9 2268
Tanmoy Bhattacharya wrote: Hi,
Hey, it's been a while, hasn't it? Welcome back!
This is a question about whether I am right that a particular syntactic sugar is missing in C++. [...] More fundamentally, is there a reason (implementation difficulty, difficulty of specification, neatness) because of which `explicit operator' is not in the language? Constructors and conversions work very similarly most of the time, so why this asymmetry?
Actually, I recall recently seeing some discussion about this in either
comp.lang.c++.moderated or in comp.std.c++ (or both). I think the answer
to this is that it's not going to help you, IIUIC.
You specifically don't want
Complex a(1,2);
if (a > 0) ...
to be legal but you do want
Complex a(1,2);
double r(a);
to be legal. But there is no difference between the two. 'a' is either
going to be converted to 'double' when a 'double' is expected or not.
If you provide a conversion operator, making it explicit will force you
to write, e.g.,
Complex a(1,2);
double r(double(a));
but you already have that ability by calling '.realpart()'.
Making constructors explicit forces somebody to write 'Type(arg)' instead
of letting the compiler figure out that 'Type' should be constructed from
the 'arg'. So, making 'Type::operator Type2()' to be explicit does not
miraculously allow _some_ conversions while disallowing other.
That's my take on it, anyway.
V
Victor Bazarov <v.********@comAcast.net> wrote in message news:<oy****************@newsread1.dllstx09.us.to. verio.net>...
(Parts snipped without indication) Hey, it's been a while, hasn't it? Welcome back!
Yeah ... got a bit too busy with things.
You specifically don't want
Complex a(1,2); if (a > 0) ...
to be legal but you do want
Complex a(1,2); double r(a);
to be legal. But there is no difference between the two. 'a' is either going to be converted to 'double' when a 'double' is expected or not.
Correct.
Making constructors explicit forces somebody to write 'Type(arg)' instead of letting the compiler figure out that 'Type' should be constructed from the 'arg'.
And allows you to write Type x(arg), though not Type x = arg.
So, making 'Type::operator Type2()' to be explicit does not miraculously allow _some_ conversions while disallowing other.
The semantics I desire is for explicit Type::operator Type2() (or
explicit operator ::Type2(Type) if such were to be allowed instead) to
behave identically to explicit Type2::Type2(Type).
Thanks (and thanks for the hint of previous discussion... I googled
some from 1996 as well!)
Tanmoy
"তন্ময়
ভট্টাচার্য্য"
<ta****@mindspring.com> wrote... Victor Bazarov <v.********@comAcast.net> wrote in message news:<oy****************@newsread1.dllstx09.us.to. verio.net>... (Parts snipped without indication) [...] Making constructors explicit forces somebody to write 'Type(arg)' instead of letting the compiler figure out that 'Type' should be constructed from the 'arg'.
And allows you to write Type x(arg), though not Type x = arg.
Right. So, making 'Type::operator Type2()' to be explicit does not miraculously allow _some_ conversions while disallowing other.
The semantics I desire is for explicit Type::operator Type2() (or explicit operator ::Type2(Type) if such were to be allowed instead) to behave identically to explicit Type2::Type2(Type).
I am not sure I follow. This is how it is now:
struct Type {};
struct Type2 {
explicit Type2(Type);
};
Type arg;
Type2 x(arg);
Type2 y = arg; // error -- no conversion exists
So, now replacing the constructor in Type2 with the cast in Type
struct Type2 {};
struct Type {
explicit operator Type2();
};
should allow
Type arg;
Type2 x(arg); // OK
Type2 y = arg; // error
, right? What I don't understand is how the conversion operator's being
explicit would affect the construction of Type2. Essentially, the two
forms
Type2 x(arg);
and
Type2 y = arg;
are using the same constructor, Type2(Type2 const&), provided by the
compiler, where the reference is bound to a temporary object created from
'arg'. There is no other constructor to use, is there? So, they both
are like
Type2 const& rtemp(arg.operator Type2());
Type2 z(rtemp);
and if we forego the creation of the temporary (as allowed), they both
are equivalent to
Type2 z(arg.operator Type2());
How are you going to make the compiler distinguish between 'Type2 x(arg)'
and 'Type2 x = arg', when the [other part of the ] language says that they
are the same? Conclusion: introduction of 'explicit' type conversion ops
will require other fundamental changes to the language, which will most
likely affect _tons_ of existing programs. Besides, it's unclear that such
change _can_ be done.
..Shrug.
I hope you find plenty of more logical explanations in the other threads
on Google.
Victor
Victor Bazarov wrote: How are you going to make the compiler distinguish between 'Type2
x(arg)' and 'Type2 x = arg', when the [other part of the ] language says that
they are the same? Conclusion: introduction of 'explicit' type conversion
ops will require other fundamental changes to the language, which will
most likely affect _tons_ of existing programs. Besides, it's unclear
that such change _can_ be done.
Thanks for your analysis. I, however, have difficulty following your
argument in detail. It is not quite correct that Type2 x(arg) and
Type2 x=arg are identical: the former calls the explicit constructor
for Type2::Type2(Type) if it exists, whereas the latter cannot call
that. In other words, yes, both are supposed to call
Type2::Type2(Type) if it exists, but the difference is whether an
explicit Type2::Type2(Type) participates in the resolution.
Similarly, it would be nice if when Type2::Type2(Type) did not exist
(to avoid ambiguity), but an `explicit' version of Type::operator
Type2() existed, it would participate in resolution only in the former,
and not the latter, case. Again, though in both cases the copy
constructor is invoked as Type2::Type2(arg.Type::operator Type2()), the
question is only whether declarations of Type::operator Type2 that are
marked `explicit' should participate.
Note that the compiler is supposed to known the semantics of the
(impicit) copy constructor, and it is typically elided in this case, so
it is difficult to argue that it is a hardship to remember the direct
initialization context in this case.
I do not see how this affects any existing code that is correct. An
example would help. I am not suggesting that something other than the
copy constructor be used, nor that something other than the conversion
operator be used: only suppress the use of the conversion under certain
conditions.
But maybe given the extensive discussion of the whole issue in
comp.std.c++ in 1996, still available on google, we should take the
discussion off-line. Incidentally, that discussion was mainly
concerned with using static_cast<double>, with which you probably would
have no quarrel, rather than direct initialization of double, though
this was briefly mentioned as well.
Tanmoy
<ta****@mindspring.com> wrote... [...] I do not see how this affects any existing code that is correct. An example would help. I am not suggesting that something other than the copy constructor be used, nor that something other than the conversion operator be used: only suppress the use of the conversion under certain conditions.
You'd need to state those conditions. I presented this example:
class Type2 {};
class Type {
operator Type2();
};
Type arg;
Type2 x(arg); // 1
Type2 x = arg; // 2
Explain what certain conditions apply here to allow suppression of
Type::operator Type2 used in the case (2), if you think this might
be beneficial.
But maybe given the extensive discussion of the whole issue in comp.std.c++ in 1996, still available on google, we should take the discussion off-line. Incidentally, that discussion was mainly concerned with using static_cast<double>, with which you probably would have no quarrel, rather than direct initialization of double, though this was briefly mentioned as well.
Well, I'd have to study the 1996 discussion to be able to participate
in any even off-line conversation (if you'd like to continue). I only
have one comment: it seems that you yourself noted that it would really
be a true syntactic sugar (given it's possible to implement), and it's
not like a serious problem that can be solved by making operators
explicit has been overlooked. Perhaps the absence of the real need
is what holds the introduction back...
V
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<FKBkd.27407$5K2.6721@attbi_s03>... You'd need to state those conditions. I presented this example:
class Type2 {}; class Type { operator Type2(); };
Type arg; Type2 x(arg); // 1 Type2 x = arg; // 2
Explain what certain conditions apply here to allow suppression of Type::operator Type2 used in the case (2), if you think this might be beneficial.
I thought I did exactly that in my previous post: the proposed rule
would be that a Type::operator Type2() declared as explicit will be
used only in two cases: (1) when Type appears as the only parameter of
an explicit constructor or direct initialization, and (2) when a
static or C-style cast operator is used. In the first of these, the
copy constructor of Type2 must be accessible, though it can be elided.
It is specifically not used when the conversions called for are
implicit *and* are not being used in a direct initialization. Note
that // 2 in your code is an initialization, but not direct
initialization, but // 1 is.
To complete the symmetry, one could also have that an explicit
constructor be useable in (2) in this paragraph. (i.e. Not only
Type2(Type), but also (Type2)Type would be able to use an explicit
constuctor for Type2): this is, however, a change which might
theoretically affect some programs, though I doubt
it occurs too often.
It turns out that the second of the two is more important, especially
for templates. The idea is that if I have a function which works on
say the string representation of its parameter, it is tempting to
write `template <T> f(T x) { String y(x); /* use y */}' or that String
y(x) bit is written as `String y = static_cast<String>(x)'. Note that
this avoids namespace pollution: the template writer does not force a
particular name like toString which must appear for people to be using
the template: it must only support the initialization or the static
cast. And, in fact, this is precisely where explicit constructors are
useful: an explicit constructor for String(T) is all that is needed to
make this work. Unfortunately, this needs access to the String class
definition, which users should not necessarily have; and, moreover, it
is impossible if a non-class type like double is substituted for
string in this example.
The point is that the need for `explicit' in the constructor is
orthogonal to the access requirements to the internals of the class,
and even to the interface of the class. Ergo, `explicit', if it
exists, should not need a change to the class definition as it
currently does.
Well, I'd have to study the 1996 discussion to be able to participate in any even off-line conversation (if you'd like to continue). I only have one comment: it seems that you yourself noted that it would really be a true syntactic sugar (given it's possible to implement), and it's not like a serious problem that can be solved by making operators explicit has been overlooked. Perhaps the absence of the real need is what holds the introduction back...
It was a nice discussion a long time back. It turns out that, as
explained variously and repeatedly on the thread, the original
proposal was to have both explicit constructors and explicit
conversion operators, though I did not find the originally intended
semantics mentioned on the thread (it certainly would have allowed the
static cast<Type2>, and disallowed calling a non-constructor function
with parameter Type2). This was the intent of the proposer, as well
as some of the committee members. The actual text of the proposal,
however, did not mention the operators, and that is how some else
interpreted it. The difference came to light only after the standard
became pretty final, and it was not considered worth changing it.
So, you are right that the `absence of the real need is what holds the
introduction back', but there does exist, and did exist, a perceived
need all along.
In any case, thanks for pointing me to the discussion. And, now I
will go back to my slumber till I learn how to google well.
Tanmoy ta****@mindspring.com (তন্ময় ভট্টাচার্য্য) wrote in message news:<61*************************@posting.google.c om>...
[content snipped]
But, seriously dude. Why would you copy/paste your handle from a
Microsoft product? Did you need to spell check it?
Anyway, in order to avoid that cruft, you do the following if you
*must* edit in Word or whatever. Copy/paste it into notepad first.
That will cause all the "mystery" formatting to be dropped in
favour of plain old ASCII text. Then copy it to your news reader.
Socks pu*********@hotmail.com wrote: ta****@mindspring.com (তন্ময় ভট্টাচার্য্য) wrote in message news:<61*************************@posting.google.c om>... [content snipped]
But, seriously dude. Why would you copy/paste your handle from a Microsoft product? Did you need to spell check it?
Anyway, in order to avoid that cruft, you do the following if you *must* edit in Word or whatever. Copy/paste it into notepad first. That will cause all the "mystery" formatting to be dropped in favour of plain old ASCII text. Then copy it to your news reader.
There is no ASCII text in whatever lies between the parentheses.
It's Bengali. And it's in Netscape's version of UNICODE, I guess.
V pu*********@hotmail.com wrote in message news:<c7**************************@posting.google. com>... ta****@mindspring.com (তন্ময় ভট্টাচার্য্য) wrote in message news:<61*************************@posting.google.c om>...
confusing my name with microsoft formatting. At least noone thought
it was an APL program!
Seriously, news and web are two different media, and even Google
should have known that. It used html entities to represent unicode
characters, instead of mime-encoding in utf-8 or something. After
this post, I promise to spelll my name in a more conventional fashion.
Thanks for pointing it out to me
Tanmoy This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Stub |
last post by:
Docs says that "The compiler does not use an explicit constructor to
implement an implied conversion of types. It's purpose is reserved
explicitly...
|
by: Dave |
last post by:
Hello NG,
Can anybody fathom the purpose of an explicit copy constructor? On page 232
of the Josuttis STL reference, I see a reference to such....
|
by: spamadress |
last post by:
Hello
I wonder why only constructors can be qualified with explicit to
prevent implicit conversion, but not conversion operators. To me the...
|
by: Ken Tough |
last post by:
Seems like a simple thing to find out, but I'm struggling. I have
googled, but everything I find is about implicit conversion,
not explicit.
Is...
|
by: Alex Sedow |
last post by:
Why explicit conversion from SomeType* to IntPtr is not ambiguous (according
to standart)?
Example:
// System.IntPtr
class IntPtr
{
public...
|
by: Michael C |
last post by:
If a class inherits from another class, say Form inherits from control, then
I can assign the Form to a variable of type Control without needing an...
|
by: petschy |
last post by:
hello,
i've run into an error when qualifying a copy ctor 'explicit'. the
strange thing is that i get a compiler error only if the class is a...
|
by: coder_lol |
last post by:
Thanks everyone again for contributing to helping me clear C++
confusions. I did some serious reading on copy constructors and
assignments and I...
|
by: Rahul |
last post by:
Hi Everyone,
I have the following code and i'm able to invoke the destructor
explicitly but not the constructor. and i get a compile time error...
|
by: jalbright99669 |
last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function.
Here is my code.
...
|
by: Matthew3360 |
last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
|
by: AndyPSV |
last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...
|
by: Arjunsri |
last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and...
|
by: Matthew3360 |
last post by:
Hi,
I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web...
|
by: Carina712 |
last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand....
|
by: BLUEPANDA |
last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS...
| |