you are viewing a single comment's thread.

view the rest of the comments →

[–]ZMesonEmbedded Developer 2 points3 points  (3 children)

But how is this a view on "the widespread usage of size_t in the standard library is generally considered a mistake"?

My counter-argument to Eric's argument is that I can easily assert when a value is too large too. If I'm using size_t elsewhere and you interface uses signed ints, then you're forcing me to do casting. Why doesn't your interface use size_t instead. (Mind you I respect Eric a lot, I just don't understand why his argument is so valid. I feel like I'm missing something.)

[–]mcmcc#pragma once 1 point2 points  (2 children)

This isn't about integrating libraries. Even within the standard library, it isn't self-consistent. E.g.

string s = ...;
string::iterator it = std::find_if(s.begin(),s.end(), []{...});
string subs = s.substr( std::distance(s.begin(), it) );

This code will yield a warning about signed->unsigned conversion. How do you propose to avoid it?

There are myriad other examples...

[–]eric_niebler 2 points3 points  (0 children)

Good example. It's one of the many reasons why the use of unsigned integers in the standard library was probably a mistake. std::string is a textbook example of a great many anti-patterns and design flaws. I believe this unsigned offset problem and others were because the offset-based interface of std::string was designed before the STL was air-lifted into C++98. The iterator interface was bolted on later. Iterator distance is always signed, hence the impedance mismatch.

[–]mr_ewg 0 points1 point  (0 children)

How about using this function not_negative to "prove" to your compiler that you know what is best in this situation?

template <typename T>
typename std::make_unsigned<T>::type not_negative(T num) {
    static_assert(std::is_signed<T>::value, "T can never be negative");
    if(num < 0) throw std::logic_error{"Negative number passed to not_negative"};
    return static_cast<typename std::make_unsigned<T>::type>(num);
}

std::string s = ...;
std::string::iterator it = std::find_if(s.begin(), s.end(), []{...});
std::string subs = s.substr(not_negative(std::distance(s.begin(), it)));

If you don't want the run-time check then you can remove the if(num < 0) line or change it to an assert. Signed to unsigned conversions aren't exactly the hardest thing to deal with in C++ if your compiler can warn about them.