Why is overloading operator&() prohibited for classes stored in STL containers?
Asked Answered
C

3

7

Suddenly in this article ("problem 2") I see a statement that C++ Standard prohibits using STL containers for storing elemants of class if that class has an overloaded operator&().

Having overloaded operator&() can indeed be problematic, but looks like a default "address-of" operator can be used easily through a set of dirty-looking casts that are used in boost::addressof() and are believed to be portable and standard-compilant.

Why is having an overloaded operator&() prohibited for classes stored in STL containers while the boost::addressof() workaround exists?

Coaming answered 27/4, 2010 at 8:46 Comment(5)
Out of curiosity (no criticism, really just curiosity), where would you overload the address-of operator?Ouphe
@roe: In classes like ATL::CComPtr (msdn.microsoft.com/en-us/library/ezzw7k98(VS.80).aspx) that makes sence. You often use them instead of raw pointers. You'd like calls to function like HRESULT GetStuff( IInterface** ) to be made for CComPtr<IInterface> and that reguires to have either a method to retrieve the address of the encapsulated pointer or overloaded operator&().Coaming
After a quick browse to the chapter on containers in the standard I have not found such a claim. Disclaimer: I just browsed over, I might have missed it if it was not in bold letters and/or the beginning of the sentence :)Tester
@David: the CopyConstructible requirements (20.1.3) specify that &t has type T* and "denotes the address of T". This doesn't technically prohibit overloading the operator, but does prohibit changing its behaviour.Vc
@Mike: thanks, that is what happens when you just browse through the docs :)Tester
T
6

Without having looked at the links, I suppose the tricks in boost::addressof() were invented well after the requirement to not to overload unary prefix & for objects to be held in containers of the std lib.

I vaguely remember Pete Becker (then working for Dinkumware on their standard library implementation) once stating that everyone who overloads the address-of operator and expects their standard library implementation still to work should be punished by having to implement a standard library which does this.

Turkmen answered 27/4, 2010 at 8:58 Comment(2)
It does make one wonder why overloading the address-of operator is allowed in the first place though, doesn't it?Dogface
@MadKeithV: When operator overloading was "invented" for C++, it had to be decided as to which operators should be overloadable and which shouldn't. Since there wasn't any experience back then - least not with C++ -, it had to be guessed. In hindsight it's easy to criticize these guesses. (Although, since it is indeed used, there are people who would argue that overloading unary prefix & is useful and beneficial.)Turkmen
G
2

Probably because it's less hassle to just prohibit the use of overloaded operator&() classes than to create a std::addressof() function and replace every use of & in container code with it.

Gerena answered 27/4, 2010 at 8:59 Comment(2)
The VS2010 team were reworking the whole STL anyway. That's not an argument. According to the post referred to, it's undefined behavior. (-1)Delisle
Do the VS2010 team specify the C++ standard, I thought it was more a question of why the standard is what it is? The other answer is probably better anyway, that it's a historical thing.Gerena
B
1

The standard was finalized in 1998 with fixes in 2003, whereas boost::addressof dates to early 2002.

Moreover, it's not clear that addressof is the answer. Overloads of operator&() indicate that raw pointers are supposed to be avoided. The Allocator::address member provides the best interface to get from Allocator::reference to Allocator::pointer, so in general theory, you should be able to effectively introduce an operator& override to an otherwise well-behaved class with a custom allocator.

Considering that references do almost everything that pointers do, and the Allocator interface abstracts everything else, there should be no need for raw pointers.

Convenience to the library implementers should not be an issue. The ill-defined semantics of Allocator::pointer are a problem, and what I've read so far in C++0x doesn't clear that up.

C++0x removes any mention of operator& from CopyConstructible, and furthermore doesn't require anything-Constructible for container arguments at all — the user can stick to emplace. Even vector only requires Destructible, although I suppose actually using insert or erase would require more.

(Note that, in the strictest reading, overloads are not forbidden in C++03. You are just not allowed to change the value or type of the builtin.)

Biblioclast answered 27/4, 2010 at 20:56 Comment(1)
"The standard was finalized in 1998" in 1997.Waylen

© 2022 - 2024 — McMap. All rights reserved.