 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Nicola Musatti Guest
|
Posted: Fri May 05, 2006 3:21 pm Post subject: Deprecate the use of plain pointers as standard container it |
|
|
Hallo,
I belive that the use of plain pointers as iterator types for standard
library containers should be deprecated, because it limits genericity
and portability.
The following code is valid on some platforms and not on others:
#include <vector>
#include <algorithm>
void f() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::sort(++v.begin(), v.end());
}
If std::vector<>::iterator is a pointer the expression ++v.begin() is
invalid because it attempts to modify an rvalue.
The following code gives different results on different platforms:
#include <vector>
#include <algorithm>
#include <iostream>
int * find(int * b, int * e, int d) {
return b + d < e ? b + d : e;
}
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
std::cout << ( i != v.end() ? *i : 0 ) << '\n';
}
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
Cheers,
Nicola Musatti
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Guest
|
Posted: Fri May 05, 2006 4:47 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Nicola Musatti wrote:
| Quote: | Hallo,
I belive that the use of plain pointers as iterator types for standard
library containers should be deprecated, because it limits genericity
and portability.
The following code is valid on some platforms and not on others:
#include <vector
#include <algorithm
void f() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::sort(++v.begin(), v.end());
}
If std::vector<>::iterator is a pointer the expression ++v.begin() is
invalid because it attempts to modify an rvalue.
|
Which opens the question: why does it try to modify an rvalue? Why not
use v.begin()+1 instead? As written, this code pointlessly specifies an
additional operation that doesn't need to be performed, which is
harmless when that operation can be performed, but fails when it can't
be. I don't think this example provides strong support for your
argument. It does provide support for the idea that your code should
never specify any actions beyond those that actually need to be taken,
even if those extra actions seem harmless.
| Quote: | The following code gives different results on different platforms:
#include <vector
#include <algorithm
#include <iostream
int * find(int * b, int * e, int d) {
return b + d < e ? b + d : e;
}
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
std::cout << ( i != v.end() ? *i : 0 ) << '\n';
}
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
|
"Doctor, it hurts when I hit myself in the head with a hammer."
"Then stop hitting yourself in the head with a hammer."
Use std::find(), if you want to make sure that it's actually
std::find() that you're calling. If you actually want the compiler to
consider other possible overloads, make sure that any other overload
that could be selected has acceptable semantics, and doesn't lead to
ambiguity as to which overload should be selected. This is the same
advice that applies whenever calling any function; there's nothing
special about the fact that v.begin() might (or might not) be a
pointer.
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
James Dennett Guest
|
Posted: Fri May 05, 2006 8:12 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Nicola Musatti wrote:
| Quote: | Hallo,
I belive that the use of plain pointers as iterator types for standard
library containers should be deprecated, because it limits genericity
and portability.
The following code is valid on some platforms and not on others:
#include <vector
#include <algorithm
void f() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::sort(++v.begin(), v.end());
}
If std::vector<>::iterator is a pointer the expression ++v.begin() is
invalid because it attempts to modify an rvalue.
|
std::sort(boost::next(v.begin()), v.end());
works and is generic (and of course boost::next is
trivial to implement).
| Quote: | The following code gives different results on different platforms:
#include <vector
#include <algorithm
#include <iostream
int * find(int * b, int * e, int d) {
return b + d < e ? b + d : e;
}
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
std::cout << ( i != v.end() ? *i : 0 ) << '\n';
}
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
|
What's to say that std::vector<T>::iterator might not be
a UDT defined in a namespace nested within ::std? In that
case your code might also find no "find", or the wrong
"find"? It sounds like you wish to require that the
iterators must be of a type defined in namespace ::std;
the question is whether the benefit is worth the cost,
which might be slower performance on some systems (as
well as possibly encouraging people to write code in a
less robust style by relying on ADL where it's not needed).
-- James
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Fri May 05, 2006 9:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Nicola Musatti wrote:
| Quote: |
The following code is valid on some platforms and not on others:
std::sort(++v.begin(), v.end());
|
This form is valid on all platforms:
std::sort(v.begin() + 1, v.end());
| Quote: | std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
|
If you need to insist on the std version, you can say so:
std::vector<int>::iterator i = std::find(v.begin(), v.end(), 2);
And note that the actual change would be to the container requirements,
not to vector. These minor problems are also present for user-defined
container types that return pointers as iterators.
--
Pete Becker
Roundhouse Consulting, Ltd.
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Seungbeom Kim Guest
|
Posted: Fri May 05, 2006 9:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
kuyper (AT) wizard (DOT) net wrote:
| Quote: | Nicola Musatti wrote:
Hallo,
I belive that the use of plain pointers as iterator types for standard
library containers should be deprecated, because it limits genericity
and portability.
The following code is valid on some platforms and not on others:
#include <vector
#include <algorithm
void f() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::sort(++v.begin(), v.end());
}
If std::vector<>::iterator is a pointer the expression ++v.begin() is
invalid because it attempts to modify an rvalue.
Which opens the question: why does it try to modify an rvalue? Why not
use v.begin()+1 instead?
|
Maybe, for consistency across different types of containers?
When v is changed into a std::list<int>, you cannot say v.begin()+1
but only ++v.begin().
Of course we have portable solutions like boost::next, but one might
think of it as rather silly to have to depend on an external library
for such a simple thing, or one might not have it in hand in the
environment he/she is working in, or one might not be allowed to use
an external library (as often in school classes). Of course it's trivial
to implement, but it's still a nuisance...
Moreover, Table 68 [Optional sequence operations] mentions --end() too:
expression
a.back()
return type
reference; const_reference for constant a
operational semantics
*--a.end()
container
vector, list, deque
so it's certainly implying that things like --a.end() should work for
containers vector, list, and deque (even though one may argue it's only
an operational "semantics").
I'm not necessarily advocating the deprecation of plain pointers as
iterators to vector, but there seem to be some good reasons why people
expect and hope ++begin() and --end() to work.
Maybe the best resolution would be to incorporate boost::next and
boost::prior into the standard, but I don't see it even in TR1...
--
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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Thorsten Ottosen Guest
|
|
| Back to top |
|
 |
Guest
|
Posted: Sat May 06, 2006 3:21 am Post subject: disambiguation rules (was: Deprecate the use of plain pointe |
|
|
kuyper (AT) wizard (DOT) net wrote:
| Quote: | Nicola Musatti wrote:
..
The following code gives different results on different platforms:
#include <vector
#include <algorithm
#include <iostream
int * find(int * b, int * e, int d) {
return b + d < e ? b + d : e;
}
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(1);
std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
std::cout << ( i != v.end() ? *i : 0 ) << '\n';
}
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
"Doctor, it hurts when I hit myself in the head with a hammer."
"Then stop hitting yourself in the head with a hammer."
Use std::find(), if you want to make sure that it's actually
std::find() that you're calling. If you actually want the compiler to
consider other possible overloads, make sure that any other overload
that could be selected has acceptable semantics, and doesn't lead to
ambiguity as to which overload should be selected. This is the same
advice that applies whenever calling any function; there's nothing
special about the fact that v.begin() might (or might not) be a
pointer.
.. |
In this example, it's clear that it would be better if the function
from the namespace implied by the parameter took precedence
over the function in the namespace of the call. What is the
rational for the order of precedence?
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Sat May 06, 2006 8:21 am Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
* Thorsten Ottosen:
Titled "Crazy ideas", but they're not at all crazy. Change the title.
Also, I think it would be a good idea to add inclusion of pi and e
constants in <cmath> and/or <limits>.
There is existing practice for pi: having M_PI in <math.h>, but the
uppercase stems from the C heritage and may conflict with macro naming.
Here's a list of <math.h> constants from one very popular compiler:
M_E e 2.71828182845904523536
M_LOG2E log2(e) 1.44269504088896340736
M_LOG10E log10(e) 0.434294481903251827651
M_LN2 ln(2) 0.693147180559945309417
M_LN10 ln(10) 2.30258509299404568402
M_PI pi 3.14159265358979323846
M_PI_2 pi/2 1.57079632679489661923
M_PI_4 pi/4 0.785398163397448309616
M_1_PI 1/pi 0.318309886183790671538
M_2_PI 2/pi 0.636619772367581343076
M_2_SQRTPI 2/sqrt(pi) 1.12837916709551257390
M_SQRT2 sqrt(2) 1.41421356237309504880
M_SQRT1_2 1/sqrt(2) 0.707106781186547524401
I suggest adding the logically missing constants (of the same form as
above) and using a nesting class like
namespace std
{
template< typename FloatingPointType >
struct constant
{
static const FloatingPointType e = ...;
static const FloatingPointType log2e = ...;
static const FloatingPointType log10e = ...;
static const FloatingPointType ln2 = ...;
static const FloatingPointType ln10 = ...;
static const FloatingPointType pi = ...;
static const FloatingPointType half_pi = ...;
static const FloatingPointType quarter_pi = ...;
static const FloatingPointType inv_pi = ...;
static const FloatingPointType two_inv_pi = ...;
static const FloatingPointType sqrt_pi = ...;
static const FloatingPointType inv_sqrt_pi = ...;
static const FloatingPointType two_inv_sqrt_pi = ...;
static const FloatingPointType sqrt_two = ...;
static const FloatingPointType inv_sqrt_two = ...;
};
}
where having it as a template allows extern linkage compile time
constants (if that matters) and the compiler's best precision per type.
Usage would be like
typedef std::constant<double> DoubleC;
...
std::cout << DoubleC::pi << std::endl;
Perhaps somebody will suggest placing the constants in
std::numeric_limits. After all, some other "constants" live there.
However, those are "constants" relating to each type's limits, and
furthermore, people refraing from using std::numeric_limits (except in
template code) because of the verbosity and non-constantness: INT_MAX
(short constant), not std::numeric_limits<int>::max() (long call).
Motivation: (1) get the compiler's best precision, (2) avoid errors, (3)
increase readability and writeability of code, (4) ease the process of
analyzing code (a good IDE can give automatic tooltip for e.g.
std::d::pi), and, not the least, (5) it's not just silly but plain
stupid to not have pi and e constants, it's "the language with no pi".
When I've mentioned this earlier the answer has always been that
nobody's proposed it. So, why not include it in the proposal list?
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Greg Herlihy Guest
|
Posted: Sat May 06, 2006 6:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Alf P. Steinbach wrote:
| Quote: | * Thorsten Ottosen:
Please see
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1870.html#add-iterator-utilities-from-boost
Titled "Crazy ideas", but they're not at all crazy. Change the title.
Also, I think it would be a good idea to add inclusion of pi and e
constants in <cmath> and/or <limits>.
There is existing practice for pi: having M_PI in <math.h>, but the
uppercase stems from the C heritage and may conflict with macro naming.
Here's a list of <math.h> constants from one very popular compiler:
M_E e 2.71828182845904523536
M_LOG2E log2(e) 1.44269504088896340736
M_LOG10E log10(e) 0.434294481903251827651
M_LN2 ln(2) 0.693147180559945309417
M_LN10 ln(10) 2.30258509299404568402
M_PI pi 3.14159265358979323846
M_PI_2 pi/2 1.57079632679489661923
M_PI_4 pi/4 0.785398163397448309616
M_1_PI 1/pi 0.318309886183790671538
M_2_PI 2/pi 0.636619772367581343076
M_2_SQRTPI 2/sqrt(pi) 1.12837916709551257390
M_SQRT2 sqrt(2) 1.41421356237309504880
M_SQRT1_2 1/sqrt(2) 0.707106781186547524401
|
The POSIX technical standard defines these 13 symbolic constants in
math.h (see X/Open CAE System Interfaces and Headers Issue 4, Version 2
pg. 780 from http://www.opengroup.org). Note that POSIX does not
require that these symbols be defined as macros - so it would certainly
be permissible to declare them as const doubles for a C++ compiler.
And while the C++ standard could also add these (or similar) constants
to math.h (or cmath), it's not likely gain much. Most C++ programs are
compiled on POSIX compliant OSes today, which means that, as a
practical matter, these symbols are already available to almost any C++
programmer who wishes to use them in a program.
Greg
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Thorsten Ottosen Guest
|
Posted: Sat May 06, 2006 6:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Alf P. Steinbach wrote:
I think people can see beyond the title.
| Quote: | Also, I think it would be a good idea to add inclusion of pi and e
constants in <cmath> and/or <limits>.
|
Then please write a proposal :-)
| Quote: |
Usage would be like
typedef std::constant<double> DoubleC;
...
std::cout << DoubleC::pi << std::endl;
|
I don't know if the typedef is needed. However, you want to
check up on the constexpr proposal. Basically, you want to make all the
constant constexpr functions, like
template<>
struct constants<float>
{
static constexpr float pi() { return 3.14....; }
...
}:
This will make vaules avaible at compile-time.
| Quote: | When I've mentioned this earlier the answer has always been that
nobody's proposed it. So, why not include it in the proposal list?atic
|
Because all of those proposal eventually need a more elaborate paper.
That paper was a "feeler" acting as a basis for discussion so I could
get some directions for what would be looked kindly upon by the LWG.
If you want this to happen, I suggets you write a paper. I'll be happy
to give you feedback.
best regards
-Thorsten
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Sat May 06, 2006 9:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
thorsten.ottosen (AT) dezide (DOT) com (Thorsten Ottosen) writes:
Probably not very well. It sets up an expectation that the proposal
isn't to be taken very seriously.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sun May 07, 2006 4:21 am Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
David Abrahams wrote:
| Quote: |
Probably not very well. It sets up an expectation that the proposal
isn't to be taken very seriously.
|
Those of us in the LWG took it seriously.
--
Pete Becker
Roundhouse Consulting, Ltd.
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Thorsten Ottosen Guest
|
Posted: Sun May 07, 2006 4:21 am Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
David Abrahams wrote:
I may add that few would see them as crazy and that most people can
recognize that the issues there are real.
| Quote: |
Probably not very well. It sets up an expectation that the proposal
isn't to be taken very seriously.
|
So you would name it "14 serious ideas for C++"? <g>
I'm confident that the people can see through rhe title and the amount
of time we have used in the LWG doesn't seem to suggest anything
different. People have taken the issue just as serious as theuy would
have with any other title IMO.
-Thorsten
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Nicola Musatti Guest
|
Posted: Mon May 08, 2006 4:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
Pete Becker wrote:
| Quote: | Nicola Musatti wrote:
The following code is valid on some platforms and not on others:
std::sort(++v.begin(), v.end());
This form is valid on all platforms:
std::sort(v.begin() + 1, v.end());
|
But than the code is only valid for random access iterators i.e. is not
as generic as it could be.
| Quote: | std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
If you need to insist on the std version, you can say so:
std::vector<int>::iterator i = std::find(v.begin(), v.end(), 2);
|
My point is not how to achieve the desired behaviour, but rather that
as this concerns the standard library it should be consistent across
platforms.
| Quote: | And note that the actual change would be to the container requirements,
not to vector. These minor problems are also present for user-defined
container types that return pointers as iterators.
|
You are right, but I don't see these as counterarguments to my point of
view.
Cheers,
Nicola Musatti
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Nicola Musatti Guest
|
Posted: Mon May 08, 2006 4:21 pm Post subject: Re: Deprecate the use of plain pointers as standard containe |
|
|
James Dennett wrote:
| Quote: | Nicola Musatti wrote:
[...]
If std::vector<>::iterator is a pointer the expression ++v.begin() is
invalid because it attempts to modify an rvalue.
std::sort(boost::next(v.begin()), v.end());
|
Imagine for a moment that you are teaching the standard library to not
very expert C++ programmers. Would you really be happy to tell them
that in order to advance an iterator one position they need to call a
third party function? But, wait, it will probably be in the standard in
less than five years!
| Quote: | works and is generic (and of course boost::next is
trivial to implement).
|
It's still much clumsier than ++v.begin() .
[...]
| Quote: | int * find(int * b, int * e, int d) {
return b + d < e ? b + d : e;
}
|
// ...
| Quote: | std::vector<int>::iterator i = find(v.begin(), v.end(), 2);
std::cout << ( i != v.end() ? *i : 0 ) << '\n';
If std::vector<>::iterator is a pointer the user defined find function
is chosen.
What's to say that std::vector<T>::iterator might not be
a UDT defined in a namespace nested within ::std? In that
case your code might also find no "find", or the wrong
"find"? It sounds like you wish to require that the
iterators must be of a type defined in namespace ::std;
|
No, I'm merely saying that the syntax and behaviour of the standard
library should be consistent across platforms, which it's not.
| Quote: | the question is whether the benefit is worth the cost,
which might be slower performance on some systems (as
well as possibly encouraging people to write code in a
less robust style by relying on ADL where it's not needed).
|
Are you suggesting that pitfalls should be carefully sprinkled
throughout the language so that people could learn more from
experience? As to the performance related argument I'm aware of its
existance and I consider it the most concrete one against my proposal.
On the other hand the deprecation mechanisim is there exactly in order
to guarantee compiler vendors enough time to fix things.
Cheers,
Nicola Musatti
---
[ 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.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
|
|
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
|
|