I can not agree. in my opinion stoi(str.view(pos)) is much worse than the straightforward stoi(str, pos).
stoi(str.view(pos)) only confuses readres because str.vew has an additional semantic that is not required in this case. It only arises questions. str.view is something else apart from str itself.This expression stoi(str, pos). is more clear .
And moreover relative to the argument list it is similar to calls of other member functions of the class We have a string and we have a position in the string. Why do we need something else?!On the other hand this expression str.view(pos) looks like we are going to call some method for the argument pos.
That is the whole expressionstoi(str.view(pos)) looks as a two step operation.
At first we call some method with argument pos and only then we call the function itself.
It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And here is a simple demonstrative program#include <iostream>#include <string>int main()
{
std::string s( "Here is number 100 you need to extract" );
std::cout << stoul( s, s.find_first_of( "0123456789" ) ) << std::endl;
}Its output is100It is very clear code with very clear semantic that does not create some unnecessary entities.Each piece of the code also is very clear and does not arise a question.
stoul( s.view().remove_prefix(s.find_first_of( "0123456789" )))
On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?
Two operations are being done either way, either within stoi or within your code. Why should stoi be the one who is doing those two, instead of your code?
On Saturday, October 3, 2015 at 5:16:53 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?These funtions already are designed specially for std::string.
Two operations are being done either way, either within stoi or within your code. Why should stoi be the one who is doing those two, instead of your code?Delegating this operation to the functions makes your code cleaner and more clear.
On Saturday, October 3, 2015 at 10:35:47 AM UTC-4, Vlad from Moscow wrote:On Saturday, October 3, 2015 at 5:16:53 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?These funtions already are designed specially for std::string.
And that is 99% of what is wrong with those functions.
[snip]
If you pass an integer to a function, I have to look up its documentation to find out what it's doing. That's not "more clear" to me.
On Saturday, October 3, 2015 at 10:35:47 AM UTC-4, Vlad from Moscow wrote:On Saturday, October 3, 2015 at 5:16:53 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?These funtions already are designed specially for std::string.
And that is 99% of what is wrong with those functions.
If you're going to add new overloads for these functions, those overloads should not exacerbate the existing flaws; they should fix them.
Taking string_view (or becoming template functions that take basic_string_views) would be a far more reasonable proposal than what you're talking about.Two operations are being done either way, either within stoi or within your code. Why should stoi be the one who is doing those two, instead of your code?Delegating this operation to the functions makes your code cleaner and more clear.
"cleaner and more clear" is a matter of personal opinion. Code that tells me exactly what it's doing is "cleaner and more clear" to me. If you get a view and remove prefix characters from it, I know what you're doing.
If you pass an integer to a function, I have to look up its documentation to find out what it's doing. That's not "more clear" to me.
On Saturday, October 3, 2015 at 5:44:06 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 10:35:47 AM UTC-4, Vlad from Moscow wrote:On Saturday, October 3, 2015 at 5:16:53 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?These funtions already are designed specially for std::string.
And that is 99% of what is wrong with those functions.Could you elaborate what is wrong with this? Maybe the C++ Standard has a defect placing these functions in the header <string>.
If you're going to add new overloads for these functions, those overloads should not exacerbate the existing flaws; they should fix them.As for me then I see that the overloads make the functions more flexible. It is what I always need when a number is inside a string.
Taking string_view (or becoming template functions that take basic_string_views) would be a far more reasonable proposal than what you're talking about.Two operations are being done either way, either within stoi or within your code. Why should stoi be the one who is doing those two, instead of your code?Delegating this operation to the functions makes your code cleaner and more clear.
"cleaner and more clear" is a matter of personal opinion. Code that tells me exactly what it's doing is "cleaner and more clear" to me. If you get a view and remove prefix characters from it, I know what you're doing.
If you pass an integer to a function, I have to look up its documentation to find out what it's doing. That's not "more clear" to me.Without any doubts to understand your example shown above a programmer needs to read tons of the documentation. At least he must be sure that the functions you used have not some side effects.
To use a string followed by a position in the string is very natural because this pattern is used in many functions of class std:;string.
The code you showed has nothing common with the class std::string.
It only makes the program more confused because you introduced a new entity that is not required to convert a string to an arithmetic type.
This family of conversion functions is an adaptation of the corresponding C functions for class std::string.
C function deal with pointers and you can very easy to move the pointer along a string.However to do the same with objects std::string you need one more argument that specifies a position within the string.
On Saturday, October 3, 2015 at 11:16:17 AM UTC-4, Vlad from Moscow wrote:
On Saturday, October 3, 2015 at 5:44:06 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 10:35:47 AM UTC-4, Vlad from Moscow wrote:On Saturday, October 3, 2015 at 5:16:53 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 4:35:08 AM UTC-4, Vlad from Moscow wrote:It is a wrong point of view. I am not trying to do ywo operations. I am delegating this work to stoi.
And why should stoi be concerned with anything but converting a string to an integer? Why should it be concerned with offsetting the initial position of that string by some value first?These funtions already are designed specially for std::string.
And that is 99% of what is wrong with those functions.Could you elaborate what is wrong with this? Maybe the C++ Standard has a defect placing these functions in the header <string>.
I thought it would be obvious.
These functions only work with std::string.
They don't work with other string type that anyone has ever written. They don't work with std::basic_string<char, ..., MyAllocator>. They don't even have overloads for `std::u16string` or `std::u32string`.
std::basic_string is, first and foremost, a container. It manages how character data gets stored. Why should `stoi` care how character data gets stored, allocated, or anything of that nature? All `stoi` needs is a way to access a character array.
It's asinine to have to waste time copying a string just because `stoi` has an over-constrained interface. We don't need to over-constrain the interface more.
If you're going to add new overloads for these functions, those overloads should not exacerbate the existing flaws; they should fix them.As for me then I see that the overloads make the functions more flexible. It is what I always need when a number is inside a string.
No, it makes them less flexible. It only allows offsetting from the beginning, not the end.
Just because something is "what I always need" does not mean that it is "flexible".
Taking string_view (or becoming template functions that take basic_string_views) would be a far more reasonable proposal than what you're talking about.Two operations are being done either way, either within stoi or within your code. Why should stoi be the one who is doing those two, instead of your code?Delegating this operation to the functions makes your code cleaner and more clear.
"cleaner and more clear" is a matter of personal opinion. Code that tells me exactly what it's doing is "cleaner and more clear" to me. If you get a view and remove prefix characters from it, I know what you're doing.
If you pass an integer to a function, I have to look up its documentation to find out what it's doing. That's not "more clear" to me.Without any doubts to understand your example shown above a programmer needs to read tons of the documentation. At least he must be sure that the functions you used have not some side effects.
... what kind of side effects would any sane implementation have of a function called `find_first_of`?
There's defensive coding, and then there's paranoid coding. You're talking about the latter. If you assume that behind every possible function call lurks a sleeping Cthulhu ready to tear your code apart, you'll never get anywhere.
To use a string followed by a position in the string is very natural because this pattern is used in many functions of class std:;string.
And every single such function also has an overload that takes an iterator rather than an integer. Are you now suggesting we do that too?
It should be noted that many people don't like std::string's interface. So defending your position by citing its interface is like saying "look at how that garbage dump works. We need to make our code look like that!"
It should also be noted that every such function is a member function of std::basic_string. Thus, the integer value is clearly associated with the string. It's not "string followed by a position". It's `string.func_name(position)`. That's a very different thing.
`stoi` is a non-member function.
The code you showed has nothing common with the class std::string.
On Saturday, October 3, 2015 at 8:44:32 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 11:16:17 AM UTC-4, Vlad from Moscow wrote:
On Saturday, October 3, 2015 at 5:44:06 PM UTC+3, Nicol Bolas wrote:On Saturday, October 3, 2015 at 10:35:47 AM UTC-4, Vlad from Moscow wrote:These funtions already are designed specially for std::string.
And that is 99% of what is wrong with those functions.Could you elaborate what is wrong with this? Maybe the C++ Standard has a defect placing these functions in the header <string>.
I thought it would be obvious.
These functions only work with std::string.And what? And what I am speaking about? I am speaking about std::string and the functions that deal with the std::string.
I am talking about that you are trying to sell me a fur coat when i need only a missing button .:)
The C++ Standard includes a family of conversion functions like std::stoi, std::stol, std::stoul and other similar functions.They allow to convert a string to some arithmetic type.However it is not always convinient to use them when you are going to apply the function to a string starting from some non-zero position.In this case you need to use either member function substr to get the desired substring. or to use another member function c_str that to apply the corresponding C function instead of the C++ function.So I think you have already understood that I want to suggest overloading functions that have one more parameter that specifies a position in the string.For example function stoi can now look like
int stoi(const string& str, size_t* idx = 0, int base = 10);
int stoi(const string& str, std::string::size_type pos, size_t* idx = 0, int base = 10);
I think this kills the suggestion, which involves these overloads:int stoi(const string& str, size_t* idx = 0, int base = 10);int stoi(const string& str, std::string::size_type pos, size_t* idx = 0, int base = 10);But now:int v = stoi(str, NULL);results in a "ambiguous call" error. This is going to break quite a lot of code, I think. (the reason being #define NULL 0)
Given the existence of string_view::remove_prefix() I think a more interesting discussion is whether there should be an overload:stoi(string_view& str, int base = 10);which uses str.remove_prefix() to indicate how much of the input string was consumed. This would be a "breaking" change but only visavi code that has not been written yet and that could assumethat a lvalue string_view passed to stoi() is not to be touched. I think it would be possible to understand that stoi will change the string_view if possible. And it provides a very easy to use API for string to number parsing.
There is a very simple and efficient method to determine what approach is more intuitively clear.
Just give a corresponding assignment to a beginner and look how he will try to do it.
So if you ask a beginner to output all numbers in a string I assure you that his approach will look something like the following
std::string s = ...;
auto sv = std::string_view(s);
while(true)
{
auto ix = sv.find_first_of("0123456789");
if(ix == std::string::npos) break;
sv = sv.remove_prefix
(ix);
int advance;
auto value = stoi(sv, &advance);
sv = sv.remove_prefix(advance);
std::cout << value << " ";
}
sv = sv.remove_prefix
(ix);sv = sv.remove_prefix
(ix);sv = sv.remove_prefix
(ix);On Sunday, October 4, 2015 at 7:00:01 PM UTC+3, Nicol Bolas wrote:OK, it's clear we're talking past each other at this point. You prefer C-in-C++ style. You prefer convoluted code that ignores the API and is "straightforward," as defined by what poorly taught beginning programmers will tend to write.
The standards committee doesn't agree with you. They prefer ranges to passing bare integer indices around. They prefer safe coding idioms. Coding idioms that are easy to reason about and modify. Even if they introduce "new entities" or whatever.
Go ahead and write up a formal proposal if you want. You'll have to fly to a meeting and defend it, as I rather suspect you'll have a hard time finding people to defend it for you. And don't be surprised if the first comment out of the committee is, "why don't you just take a `string_view`?" And when you try to offer your justifications for your API, don't be surprised if they find it unconvincing.I hope that the C++ Standards Committee is not just you.:)
In fact your code diifers from the code of a beginner that I showed only in one thing: the code of the beginner does not use remove_prefix that you are uisng twice in one loop
By the way what about if you need not only to extract numbers but also to generate a vector of pairs { position, number }?
vec.emplace_back(sv.substr(0, advance), value);
Will ix in your code correspond to the position in the original string? Or in this case do you have to rewrite your code entirely?:)
vec.emplace_back(&sv[0] - &s[0], value);
Instead of saying many words let's compare the two resulting code snippets.This is better than any words.:)
std::string s = ...;
for ( std::string::size_type pos = 0;
( pos = s.find_first_of( "0123456789", pos ) ) != std::string::npos; )
{
std::cout << std::stoul( s, pos, &pos ) << ' ';
}
On Sunday, October 4, 2015 at 12:54:50 PM UTC-4, Vlad from Moscow wrote:On Sunday, October 4, 2015 at 7:00:01 PM UTC+3, Nicol Bolas wrote:OK, it's clear we're talking past each other at this point. You prefer C-in-C++ style. You prefer convoluted code that ignores the API and is "straightforward," as defined by what poorly taught beginning programmers will tend to write.
The standards committee doesn't agree with you. They prefer ranges to passing bare integer indices around. They prefer safe coding idioms. Coding idioms that are easy to reason about and modify. Even if they introduce "new entities" or whatever.
Go ahead and write up a formal proposal if you want. You'll have to fly to a meeting and defend it, as I rather suspect you'll have a hard time finding people to defend it for you. And don't be surprised if the first comment out of the committee is, "why don't you just take a `string_view`?" And when you try to offer your justifications for your API, don't be surprised if they find it unconvincing.I hope that the C++ Standards Committee is not just you.:)
The C++ standards committee does not even include me ;)
However, the fact of the matter is this. You explained what you wanted. Six separate people, including myself, disagree with you about which is clearer, easier for beginners, and/or more useful in general. Not one single person has stepped forward to defend your idea.
Do you honestly expect the arguments that we have found unconvincing to be more convincing when spoken to committee members? They will undoubtedly ask why you don't just suggest that the function takes a `string_view` (especially since that change is already part of an existing proposal).
Do you think that your examples will convince them? Do you believe that the people behind the range proposal will be convinced by your C-in-C++ code examples? Do you think that they will agree with you when you declare how beginners will obviously want to code?
Because at the end of the day, all you have is a feature who's functionality will be duplicated once `string_view` is added to `stoi` and so forth. You may not like the form of that duplication, but it is an irrefutable fact that you will be able to get the same job done with the `string_view` form as with what you want.
That's what you'd be fighting against.In fact your code diifers from the code of a beginner that I showed only in one thing: the code of the beginner does not use remove_prefix that you are uisng twice in one loop
You were trying to prove that beginners would never be able to use string_view, right?
So if it is true that my code is only slightly different from your idea of beginner code, then you must accept that a beginner would be equally capable of writing either one.
Doesn't that torpedo your entire argument? Either my code is so different that a beginner would never write it, or it's perfectly comprehensible to a beginner. It can't be both.
By the way what about if you need not only to extract numbers but also to generate a vector of pairs { position, number }?
That right there shows the problem with your mode of thought. You declare arbitrary requirements without bothering to ask why someone would need such a requirement.
I look at that requirement and ask what they'd do with such offsets. If they want to associate locations in the string with the number that they correspond to, then odds are good that they're probably going to want to process the text between number characters. Right? I mean, they already have the numbers themselves. So that would be a logical reason for wanting to know what part of the text a number comes from.
And if that's the case, then `{ position, number }` is seriously lacking one important element: the size of each number, in characters. You need that to know where a number ends, so that you can go on to process the characters after one number and before the next.
Given that, what you really want is a `vector<pair<string_view, int>>`. And that is easy to provide:
vec.emplace_back(sv.substr(0, advance), value);