C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Temporaries: Const or mutable?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Samee Zahur
Guest





PostPosted: Fri May 13, 2005 6:04 am    Post subject: Temporaries: Const or mutable? Reply with quote



This is a followup to two recent threads in c.l.c++
-
http://groups-beta.google.com/group/comp.lang.c++/browse_thread/thread/532943e5798f58db/e3aa4aac4225190b?q=Mutating+temporaries+author:Samee&rnum=1#e3aa4aac4225190b
-
http://groups-beta.google.com/group/comp.lang.c++/browse_thread/thread/3ae26ddfaf040d62/556029a16ad33bcd?q=Mutating+temporaries+author:Samee&rnum=2#556029a16ad33bcd


It seems that C++ treats temporary objects rather strangely
(to me at least):

- temps of built-in types and enums (or their typedefs) are always
const ... after all, statements such as 1+2=val; wouldn't make sense!

- temps of all other types are mutable if used directly - the
following is legal: myclass().mutatewith(54);
or even myclass()=54;if operator= is defined in myclass.

- the same temps when passed to a function by reference, however,
must be passed as a 'const myclass&', which means if temps are to be
mutated from within the function, a const_cast is needed (or is that
undefined?)

Why does such a discrepency exist? I mean, the whole idea of C++ is to
have user-defined types that act like 'first-class citizens', right?
Even though user-defined temporaries might often have to be mutated -
why can't something like that be done inside a function receiving it by
reference? Restrictions like these often seems to be getting in the way
of const-correctness as far as I see :(

Samee

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]

Back to top
illumanus@yahoo.com
Guest





PostPosted: Sat May 14, 2005 3:44 am    Post subject: Re: Temporaries: Const or mutable? Reply with quote



The reason temporaries are not allowed to be passed to functions
accepting arguments by reference has to do with implicit conversions.
Look at the following code:

struct MyString {
....
MyString (char *); // Defines an implicit conversion from char * to
MyString
MyString &toupper(); // Converts our string to uppercase and returns
*this
};

// Some "handy" functions
void toupper(MyString &s) { s.toupper(); };
bool isupper(const MyString &); // Returns true if our string is all
uppercase
MyString make_str() { return "Foo"; };

...

toupper("Foo"); // This will generate an error and should
// It would cause a temporary MyString to be constructed, modified then
destroyed
// Not what the coder probably intends from writing this statement.

if(isupper("Foo")) // This is ok
cout << "Foo";

if(isupper(make_str().toupper()); // This is ok too
cout << "Upper Foo"

This rule is to protect coders. Without this rule you could accidently
generate code that might appear to do something but really does nothing
and does not generate a compile time error.
Hope this helps,
Lance Gatlin

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]

Back to top
Me
Guest





PostPosted: Mon May 16, 2005 5:30 am    Post subject: Re: Temporaries: Const or mutable? Reply with quote



It doesn't really come from the constness of builtins. It comes from
the way C treats l-values and the fact that it didn't have const early
on and there was already a lot of code written. Your code touches on a
specific issue so lets take a digression:

T foo()
{
return T();
}

foo() = T();

works for structs/classes, doesn't work for primitives. Note that if T
was a struct/class, you can't do:

foo().i = 50;

The way to protect against this is:

const T cfoo()
{
return T();
}

cfoo() = T();

Now it doesn't work as expected. But note: for primitive types the
top-level const is redundant, so it generates the same function
signature. The problem with your code is that it was constructing a T
using:

T() // similar to foo()

you cannot do:

const T() // would be similar to cfoo()

because there is a space between it (except as an extension in
Microsoft's compiler which allows spaces in certain cases). You can get
around this with either a typedef:

typedef const T cT;

cT()

or with a template helper involving a typedef:

template<class T> struct ident { typedef T type; };

ident<const T>::type()

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]

Back to top
Llewelly
Guest





PostPosted: Mon May 16, 2005 4:21 pm    Post subject: Re: Temporaries: Const or mutable? Reply with quote

"Samee Zahur" <samee.zahur (AT) gmail (DOT) com> writes:

Quote:
This is a followup to two recent threads in c.l.c++
-
http://groups-beta.google.com/group/comp.lang.c++/browse_thread/thread/532943e5798f58db/e3aa4aac4225190b?q=Mutating+temporaries+author:Samee&rnum=1#e3aa4aac4225190b

http://xrl.us/f3z2
(A shortening of Samee's link in case someone's browser breaks that
looong thing.)

Quote:
-
http://groups-beta.google.com/group/comp.lang.c++/browse_thread/thread/3ae26ddfaf040d62/556029a16ad33bcd?q=Mutating+temporaries+author:Samee&rnum=2#556029a16ad33bcd

http://xrl.us/f3z2
(Shortened.)

Quote:


It seems that C++ treats temporary objects rather strangely
(to me at least):

- temps of built-in types and enums (or their typedefs) are always
const ... after all, statements such as 1+2=val; wouldn't make sense!

- temps of all other types are mutable if used directly - the
following is legal: myclass().mutatewith(54);
or even myclass()=54;if operator= is defined in myclass.

Ha, saw that yesterday in 'real code'. We has something like this:

void strip_non_hex_digits(std::vector<char>& c)
{
for
( std::vector<char>::iterator current= c.begin()
; current != c.end()
; ++current
)
{
if( !std::isxdigit(*current) )
{
current = --c.erase(current); //Using -- on a temporary.
}
}
}

gcc compiles this happily. But aCC does not. The problem? gcc defines
operator-- for iterators as a member function, which can be used
on temporaries. If it had been defined as a non-member operator--,
this would not compile. aCC doesn't compile because aCC uses
something like 'typedef T* iterator' for its vectors. (All 3
choices are allowed by the standard)

The lesson? Because of the rule you cite, defining an operator as
member is almost always a bad thing, unless the language requires
it.

There's a lot of debate about whether this rule is good or bad, but
I'm firmly convinced it was a mistake. It makes member functions
inconsistent with the rest of the language in yet another way, it
makes treatment of temporaries inconsistent, and it makes it
member operators inconsistent with built-in operators. However it
can't be fixed without breaking lots of code.

Quote:

- the same temps when passed to a function by reference, however,
must be passed as a 'const myclass&', which means if temps are to be
mutated from within the function, a const_cast is needed (or is that
undefined?)

Why does such a discrepency exist?

Plenty of member functions are important not becuase of their effects
on the values within an object, but becuase of their effects on
some state external to the object.

I don't recall specific code examples, or the many other arguments
that went into it, but you can find endless threads on this topic
in the archives. Watch out, however - in pre-standard days there
was a time when the drafts allowed temporaries to be bound to
references to non-const, and plenty of popular compilers
implemented things that way.

Quote:
I mean, the whole idea of C++ is to
have user-defined types that act like 'first-class citizens', right?
Even though user-defined temporaries might often have to be mutated -
why can't something like that be done inside a function receiving it by
reference? Restrictions like these often seems to be getting in the way
of const-correctness as far as I see Sad
[snip]


You aren't the only that thinks it's a mistake.

I seem to recall there are number of historically informative papers
at:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/
(Look before 1998. )

But I don't recall specificly which ones.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Seungbeom Kim
Guest





PostPosted: Mon May 16, 2005 4:22 pm    Post subject: Re: Temporaries: Const or mutable? Reply with quote

[email]illumanus (AT) yahoo (DOT) com[/email] wrote:
Quote:
The reason temporaries are not allowed to be passed to functions
accepting arguments by reference has to do with implicit conversions.

But there is more than that, as you see below:

Quote:
struct MyString {
....
MyString (char *); // Defines an implicit conversion from char * to
MyString
MyString &toupper(); // Converts our string to uppercase and returns
*this
};

// Some "handy" functions
void toupper(MyString &s) { s.toupper(); };
bool isupper(const MyString &); // Returns true if our string is all
uppercase
MyString make_str() { return "Foo"; };

toupper(MyString("Foo")) would not compile even if it involves no
implicit conversions.

I have been annoyed by this gratuitous restriction several times. When
the programmer explicitly wants a temporary, it should be allowed.

bool test(game&);

void test_games()
{
if (not test(game(args...)
or not test(game(different args...)
or not test(game(still different args...))
{
// we have a problem
}
}

OR

void extract_int(std::istream& is);

void extract_int(std::string& s) { extract_int(std::istringstream(s)); }

Imagine how these codes would be cluttered with meaningless declarations
even though the temporaries don't really have to be named and declared.
I feel it's silly to have to write an rvalue-to-lvalue converter such as
X& self() { return *this; } to overcome this restriction.

A bunch of references: :-)

http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/ac40d36f0cc8039b
http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/9cc442a4cb661f65
http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/96d566cb68601705
http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/67d0dcc09bdebcab
http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/2dc43f0d4dc0cf85
http://groups-beta.google.com/group/comp.lang.c++.moderated/msg/d35bedd6980e719f

Quote:
This rule is to protect coders. Without this rule you could accidently
generate code that might appear to do something but really does nothing
and does not generate a compile time error.

The protection is sometimes excessive. As you noted, it should be on the
implicit conversion, but it is actually on a bigger category of things
("temporaries" or "rvalues") now.

Isn't it ever going to be changed, really?

--
Seungbeom Kim

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Samee Zahur
Guest





PostPosted: Mon May 16, 2005 5:22 pm    Post subject: Re: Temporaries: Const or mutable? Reply with quote

Quote:
toupper("Foo"); // This will generate an error and should

Ok, I understand that this wouldn't compile, but I still don't quite
get the possible confusion. Even if I forget about the rest of the code
(and the MyString class) for a while, I'd think I am seeing a literal
string getting converted to uppercase and then getting thrown away ...
under what confusion or purpose might a programmer write something like
this, from which he has to be protected?

Samee

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Seungbeom Kim
Guest





PostPosted: Mon May 16, 2005 10:04 pm    Post subject: Re: Temporaries: Const or mutable? Reply with quote

Llewelly wrote:
Quote:

There's a lot of debate about whether this rule is good or bad, but
I'm firmly convinced it was a mistake. It makes member functions
inconsistent with the rest of the language in yet another way, it
makes treatment of temporaries inconsistent, and it makes it
member operators inconsistent with built-in operators. However it
can't be fixed without breaking lots of code.

Can you elaborate on the possibility of breaking existing codes?

Can't we avoid it if we change the rules only in the "loosening"
direction, so that some of the currently ill-formed codes turn into
well-formed ones but not the other way round?

--
Seungbeom Kim

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.