admin管理员组

文章数量:1203553

The code below

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = { 1,2,3 };

    if (std::count(v.begin(), v.end(), 1) > v.size() / 2) {
        std::cout << "Too many\n";
    } 
}

gives a warning:

(8,40) warning C4018: '>': signed/unsigned mismatch

which is quite reasonable, since std::count returns ::difference_type and size() returns ::size.

The question is, what is the robust way to handle this?

In the Comparing ptrdiff_t with size_t it is discussed how this should be implemented in compilers, but never said how to safely live with existing implementations.

For example, it is stated:

If ptrdiff_t is of greater rank than size_t and can represent all positive values of size_t. limit - buf <= sizeof buf poses no problems then.

Else ptrdiff_t may not represent all positive values of size_t and then the subtraction limit - buf may be UB per below, so the compare is moot.

Great, but under Win64 we have:

typedef unsigned __int64 size_t;
typedef __int64          ptrdiff_t;

And this is a direct indications (if containers don't use other types for ::difference_type) that size_t values won't fit to ptrdiff_t for safe calculations (it can't represent all size_t values as positive).

So, this:

    if (std::count(v.begin(), v.end(), 1) > static_cast<std::vector<int>::difference_type>(v.size() / 2)) {
        std::cout << "Too many\n";
    }

is not safe anymore.

Casting in the opposite way is unacceptable since it violates first guidance above.

So, what is the safest way to shape the code here?

Should I write a wrapper to check the sizes and return the largest type or there is something more reasonable and built-in?

The code below

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = { 1,2,3 };

    if (std::count(v.begin(), v.end(), 1) > v.size() / 2) {
        std::cout << "Too many\n";
    } 
}

gives a warning:

(8,40) warning C4018: '>': signed/unsigned mismatch

which is quite reasonable, since std::count returns ::difference_type and size() returns ::size.

The question is, what is the robust way to handle this?

In the Comparing ptrdiff_t with size_t it is discussed how this should be implemented in compilers, but never said how to safely live with existing implementations.

For example, it is stated:

If ptrdiff_t is of greater rank than size_t and can represent all positive values of size_t. limit - buf <= sizeof buf poses no problems then.

Else ptrdiff_t may not represent all positive values of size_t and then the subtraction limit - buf may be UB per below, so the compare is moot.

Great, but under Win64 we have:

typedef unsigned __int64 size_t;
typedef __int64          ptrdiff_t;

And this is a direct indications (if containers don't use other types for ::difference_type) that size_t values won't fit to ptrdiff_t for safe calculations (it can't represent all size_t values as positive).

So, this:

    if (std::count(v.begin(), v.end(), 1) > static_cast<std::vector<int>::difference_type>(v.size() / 2)) {
        std::cout << "Too many\n";
    }

is not safe anymore.

Casting in the opposite way is unacceptable since it violates first guidance above.

So, what is the safest way to shape the code here?

Should I write a wrapper to check the sizes and return the largest type or there is something more reasonable and built-in?

Share Improve this question edited Jan 21 at 10:00 463035818_is_not_an_ai 122k11 gold badges99 silver badges208 bronze badges asked Jan 20 at 21:04 Damir TenishevDamir Tenishev 3,2727 silver badges20 bronze badges 5
  • 3 See stackoverflow.com/questions/7505083/…. std::count is always <= v.size(), thus static_cast<size_t> is safe. – 3CxEZiVlQ Commented Jan 20 at 21:22
  • The size of size_t and ptrdiff_t is not the only criterion, vector's max_size should be small enough that size fits in ptrdiff_t (otherwise the implementation would let you create a broken vector that cannot be accessed properly). – Marc Glisse Commented Jan 20 at 22:34
  • @3CxEZiVlQ except that std::count can be negative (which probably means the code is buggy, but that's aside). – rustyx Commented Jan 20 at 23:32
  • 1 You could use std::cmp_greater to handle different signs. – BoP Commented Jan 21 at 10:26
  • If there is a danger of your vector having more than 9223372036854775807 elements, then you could consider using a 128-bit integer (e.g., absl::int128). – Eljay Commented Jan 21 at 12:33
Add a comment  | 

1 Answer 1

Reset to default 3

The issue is between a signed and unsigned integer value. Vector does not have an unsigned ssize function. Instead, use the ssize() from the standard or ranges library.

auto main() -> int {

   std::vector<int> v = { 1,2,3 };

   if (std::count(v.begin(), v.end(), 1) > std::ssize(v) / 2) {
      std::cout << "Too many\n";
   }

   return 0;
}

本文标签: cHow to compare sizet and differencetypeStack Overflow