5

To increase the performance I'm trying to substitute std::string with custom specializations of std::basic_string where I'm replacing standard allocator with custom ones. One thing surprised me: the std::stoi class of functions requires constant references to std::string (or std::wstring) as an input, so these functions don't work with other specializations. But logically these functions shouldn't care of how the memory is allocated; so their signatures look overly limiting.

While I could use the std::from_chars to read integers from any string-like data, I still wonder whether there was a reason why std::stoi is designed that way, and whether there are other STL functions designed to work with std::basic_string templates.

Dmitry Kuzminov
  • 6,180
  • 6
  • 18
  • 40
  • 2
    I am surprised that the are not defined for `std::string_view` in the first place. – alfC Aug 01 '23 at 04:58
  • 3
    Looks like it might be a standard defect since it makes sense to support `std::pmr::string` too. But for C++17, `stoi` should be completely replaced by `from_chars`, so I don't see a reason why it really needs to be fixed. – 康桓瑋 Aug 01 '23 at 06:02
  • @alfC `std::string_view` is not guaranteed to be null-terminated, but the C function being called internally requires a null-terminated string. – Remy Lebeau Aug 01 '23 at 06:28
  • @RemyLebeau, I see, I didn't know these functions were calling corresponding c-functions. It is strange anyway because, std::string can have a null character in the middle. I guess is fine because a null character is never part of an integer. – alfC Aug 01 '23 at 06:35
  • For the OP, it doesn't seem to be that there is a good solution: either call the underlying c-function or `reinterpret_cast` from your custom `basic_string` to `std::string const&`. – alfC Aug 01 '23 at 06:38

1 Answers1

-1

Because it's just a proxy function to C std::strtol(), converts its errors to C++ exceptions after a call to [1] [2]

std::strtol(str.c_str(), &ptr, base)

that takes only char*, null-terminated char array, hence other char_type specializations of std::basic_string are not accepted.

You can overload strtol for std::basic_string with your custom allocator, but you have to call it w/o std:: namespace qualification:

using std::stoi;

int stoi(const mystring& str, std::size_t* pos = nullptr, int base = 10) {
  char *ptr;
  const long ret = std::strtol(str.c_str(), &ptr, base);

  // Required checks and throwing exceptions here

  if (pos)
    pos = ptr - str.c_str();
  return static_cast<int>(ret);
}

As for std::string_view, it is not required to refer a null-terminated string, thus it does not have std::string_view::c_str() and its data() is not suitable for std::strtol().

273K
  • 29,503
  • 10
  • 41
  • 64
  • All `basic_string` specializations are null terminated. `strtol()` would work just fine with them. There is no technical reason that `stoi()` couldn't accept specializations other than the standard committee simply hasn't defined the standard that way. – Remy Lebeau Aug 01 '23 at 06:05
  • @RemyLebeau I can't find any mention of `basic_string::c_str()` in my answer. All specializations are for `char*` and `wchar_t*`, they cover all available C functions, it does not need to be a template and accept other specializations. – 273K Aug 01 '23 at 06:07
  • 1
    The whole point is that `.c_str()` will work in the exact same way for other specializations of `basic_string`. – L. F. Aug 01 '23 at 06:10
  • @L.F. What other specializations? There are no C functions for other types except `char*` and `wchar_t*`. – 273K Aug 01 '23 at 06:11
  • 1
    Sorry, I meant `std::basic_string, Alloc>` for allocators `Alloc` other than `std::allocator`. Of course the `char_type` must be `char` (or `wchar_t`). – L. F. Aug 01 '23 at 06:12
  • 2
    @273K your answer claims that because `strtol()` requires a null terminated `char*` string, `stoi()` couldn't possibly accept other specializations of `basic_string`, and that is simply not true. And in this case, the specialization being asked about is on the Allocator, not the character type. Since `stoi()` requires `std::(w)string` specifically, `basic_string` specializations that use `char`/`wchar_t` with custom allocators can't be used with `stoi()` even though `strtol()` would be just fine with it – Remy Lebeau Aug 01 '23 at 06:13
  • @RemyLebeau When I talked about a null terminated string, I talked about `string_view`. Please don't tell about what I have not said. – 273K Aug 01 '23 at 06:16
  • 1
    @273K The 1st half of your answer clearly does not talk about `string_view`. The 2nd half of your answer is technically correct, but doesn't apply to the question asked by the OP. So basically, your entire answer is wrong and needs to be fixed or deleted. – Remy Lebeau Aug 01 '23 at 06:17
  • @RemyLebeau The first half is about `char*`, not about `.c_str()`. I mentions only specializations for `char_type`. L.F. is rights that I missed specializations for allocators. – 273K Aug 01 '23 at 06:18
  • 1
    @273K The 1st half of your answer refers to `stoi()` and how it calls `strtol()`. That would work just fine with all specializations of `basic_string` that use `char`/`wchar_t` for their character type. All specializations of `basic_string` have `c_str()` – Remy Lebeau Aug 01 '23 at 06:21
  • 1
    @RemyLebeau Don't be a bath sheet, you were more kind a year ago. – 273K Aug 01 '23 at 06:22
  • 2
    @273K I'm not here to be kind. This is a Q&A site. I'm here to answer questions, and to make sure other answers are accurate and applicable to the questions being asked. Your answer does not adequately or correctly address the OP's actual question. – Remy Lebeau Aug 01 '23 at 06:26
  • I didn't ask anything about `std::string_view`. – Dmitry Kuzminov Aug 01 '23 at 14:07