4

Given the following:

code-link

Here is the code itself for convenience (and I am not sure my link is working):

#include <iostream>
#include <vector>
#include <stdint.h>

using namespace std;

int main()
{
    cout<<"Hello World";
    std::vector<std::string> test_vect {"1", "2"};
    long unsigned int size = static_cast<long unsigned int>(test_vect.size());

    std::cout << "size: " << size << std::endl;
    return 0;
}

And the following compile options: g++ file.c -Wall -Wextra "-Werror" "-Wuseless-cast"

You can see here that I am casting vector.size() to long unsigned int, this gets flagged up as a useless cast on Wandbox (my link) however the same code running on my linux box does not give a warning - but it will give me a different warning if I dont cast it.

I understand that the two unsigned long vs size_t can be different. But what I am trying to do is write some code that has no warnings with all the casting warnings set (maybe this is optamisitic when cross compiling).

So, one compiler complains that I am converting types, so I cast, but then another compiler is complaining about useless cast - so I remove the cast - and around we go :(

Is there a good approach to this so that I dont get warnings on either compilers?

I was going to just remove the -Wuseless-cast option, but I thought I would see if anyone has other ideas...

code_fodder
  • 15,263
  • 17
  • 90
  • 167
  • seems you will need an old good #ifdef – P. PICARD May 21 '19 at 10:32
  • 3
    To be honest `-Wuseless-cast` doesn't seem useful to me. I'd remove it. – HolyBlackCat May 21 '19 at 10:34
  • Ok you have provided MCVE, but it would be nice to see in what context your code does that cast, since it may open doors for other fixes. – Marek R May 21 '19 at 10:36
  • 2
    Instead of trying to store the size of the vector in an `long unsigned int`, use a `std::size_t`. That stores the result in a variable of the appropriate type, and eliminates the need for casting at all. – Peter May 21 '19 at 10:39
  • @P.PICARD It is a way around it : ) ... but I could forsee that getting annoying with more and more code... – code_fodder May 21 '19 at 10:40
  • @HolyBlackCat yeah, I think I am starting to come to that conclusion too – code_fodder May 21 '19 at 10:40
  • 1
    _"Here is the code itself for convenience"_ Not just convenience; the question _must_ be self-contained for posterity – Lightness Races in Orbit May 21 '19 at 10:41
  • @Peter the only issue with that is that we have an API that takes a `long unsigned` (well, that is just one example of the issue) - so we can't really change that part so we would have to do a conversion somewhere.. – code_fodder May 21 '19 at 10:42
  • @LightnessRacesinOrbit ... true, I guess wandox might die one day :o – code_fodder May 21 '19 at 10:43
  • Or stop storing your code. Doesn't matter. If we put the MCVE here, there is assuredly no problem. – Lightness Races in Orbit May 21 '19 at 10:44
  • 1
    @code_fodder - Your example is contrived, since that means a flawed API (if the API is intended to be cross-platform, using `unsigned long` to hold the size of a vector or the result of `sizeof` is a flaw). In any event, the obvious solution would be to change the API - if it's not in your control, submit a feature/bug request. If you can't (or, as the owner of the API, you arbitrarily won't) do that, then write a function to do the conversion. That isolates the conversion into one place, and you can use the preprocessor to help implement versions of that function for different compilers. – Peter May 21 '19 at 10:54
  • Also possible would be to use `auto size = test_vect.size()` or `decltype(test_vect.size()) size = test_vect.size()`. – nada May 21 '19 at 10:58
  • @nada Pointless. We already know what the return type is. It's `std::size_t`, always. All you've done is to mask that. – Lightness Races in Orbit May 21 '19 at 11:04
  • @LightnessRacesinOrbit Masking makes compiler happy, which is what code_fodder wants – nada May 21 '19 at 11:06
  • @nada That's changing the type of the variable which has been suggested already. Masking that change achieves nothing but confusion – Lightness Races in Orbit May 21 '19 at 11:11
  • @LightnessRacesinOrbit How is `std::size_t` different? Isn't that also masking? – nada May 21 '19 at 11:15
  • @nada: No. It clearly shows what the type is. It's `std::size_t`. When you write `auto` instead, you've _masked what that is_ because you can no longer find out the type by reading that bit of code. For no gain. – Lightness Races in Orbit May 21 '19 at 11:28
  • @LightnessRacesinOrbit True, but std::size_t is also just a mask for `unsigned long long int` on most, if not all systems. – nada May 21 '19 at 11:38
  • @nada No, it's a distinct type with specific semantics. – Lightness Races in Orbit May 21 '19 at 11:53
  • @LightnessRacesinOrbit I am not sure what that means, but I guess you are correct. – nada May 21 '19 at 12:01
  • @nada https://stackoverflow.com/a/2550799/560648 – Lightness Races in Orbit May 21 '19 at 12:13
  • `std::vector::size()` returns `std::vector::size_type`, which is *probably* the same as `std::size_t`, but who knows really. – n. m. could be an AI May 21 '19 at 14:58

3 Answers3

6

what I am trying to do is write some code that has no warnings with all the casting warnings set (maybe this is optamisitic when cross compiling)

It's optimistic when cross compiling if you have casts.

Is there a good approach to this so that I dont get warnings on either compilers?

Don't have casts. Make your variable be of type std::size_t.

I was going to just remove the -Wuseless-cast option

That's the other option.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

As Lightness Races in Orbit pointed out, size_t is an option, it should have an appropriate macro to make compilers happy, if you somehow don't want to use that - making your variable auto or decltype(test_vect.size()) would be another option:

auto size = test_vect.size();

or

decltype(test_vect.size()) size = test_vect.size();
nada
  • 2,109
  • 2
  • 16
  • 23
1

One argument that comes to mind is: Why does your size variable need to be long unsigned at all instead of std::size_t?

Just in case there is a compelling reason for that, how about (C++17):

long unsigned size;
if constexpr(sizeof(long unsigned)!=sizeof(std::size_t))
    size = static_cast<long unsigned>(...);
else
    size = ...;
Demosthenes
  • 1,515
  • 10
  • 22