C++ - "invalid narrowing conversion from "int" to "std::size_t"" [LÖST]

Permalänk
Medlem

C++ - "invalid narrowing conversion from "int" to "std::size_t"" [LÖST]

Hej,

Jag jobbar mig igenom en av mina C++-böcker och blev där rådd att byta ut arrayer som ser ut så här:

int arr[4]

mot sådana:

std::array<int, 4>

Det är nu vad jag håller på med i ett av mina program. När jag försökte göra detta:

std::array<uint64_t, thread_count> start_of_range = {}; std::array<uint64_t, thread_count> end_of_range = {};

fick jag följande fel:

invalid narrowing conversion from "int" to "std::size_t"

thread_count ser ut såhär:

int thread_count = std::thread::hardware_concurrency();

Jag förstår det som att det blir ett konverteringsfel, hur kan jag komma runt detta?

Permalänk
Medlem

Bara för att testa ett enklare exempel först.
Kompilerar detta för dig?

std::array<uint64_t, 10> a;

Visa signatur

Windows 11 Pro | Intel i7 8700 | ASUS Prime Z370-P | Corsair 16GB 3000MHz | ASUS GTX 1080 | Fractal Design Define S | Corsair RM750x | Hyper 212 EVO

Permalänk
Medlem
Skrivet av Joppis:

Bara för att testa ett enklare exempel först.
Kompilerar detta för dig?

std::array<uint64_t, 10> a;

Ja, det fungerar.

Permalänk
Medlem

En narrowing conversion är när du konverterar ett värde till en typ som kanske inte kan representera värdet. I det här fallet från int till size_t, där size_t är unsigned och kanske av en annan storlek. Sån konvertering tillåts ofta implicit i C++, men om du t.ex. använder "uniform initialization" så tillåts det inte. T.ex.:

int thread_count{std::thread::hardware_concurrency()}; // Fel eftersom hardware_concurrency returnerar en unsigned int

Lösningen i såna fall är att explicit konvertera med static_cast.

Jag vet inte varför du får det felet i det här fallet, du borde snarare få fel p.g.a. att storleken på arrayerna måste vara konstanter vilket thread_count inte är. Om du vill använda std::thread::hardware_concurrency() som storlek så får du istället använda t.ex. std::vector, eftersom antalet trådar som stöds är något som avgörs när programmet körs och inte under kompileringen.

Permalänk
Medlem
Skrivet av perost:

En narrowing conversion är när du konverterar ett värde till en typ som kanske inte kan representera värdet. I det här fallet från int till size_t, där size_t är unsigned och kanske av en annan storlek. Sån konvertering tillåts ofta implicit i C++, men om du t.ex. använder "uniform initialization" så tillåts det inte. T.ex.:

int thread_count{std::thread::hardware_concurrency()}; // Fel eftersom hardware_concurrency returnerar en unsigned int

Lösningen i såna fall är att explicit konvertera med static_cast.

Jag vet inte varför du får det felet i det här fallet, du borde snarare få fel p.g.a. att storleken på arrayerna måste vara konstanter vilket thread_count inte är. Om du vill använda std::thread::hardware_concurrency() som storlek så får du istället använda t.ex. std::vector, eftersom antalet trådar som stöds är något som avgörs när programmet körs och inte under kompileringen.

Testar nu...

Permalänk
Datavetare
Skrivet av Apollo11:

Hej,

Jag jobbar mig igenom en av mina C++-böcker och blev där rådd att byta ut arrayer som ser ut så här:

int arr[4]

mot sådana:

std::array<int, 4>

Det är nu vad jag håller på med i ett av mina program. När jag försökte göra detta:

std::array<uint64_t, thread_count> start_of_range = {}; std::array<uint64_t, thread_count> end_of_range = {};

fick jag följande fel:

invalid narrowing conversion from "int" to "std::size_t"

thread_count ser ut såhär:

int thread_count = std::thread::hardware_concurrency();

Jag förstår det som att det blir ett konverteringsfel, hur kan jag komma runt detta?

Det är intellisense för C++ som ger helt galet felmeddelande, antar att du kör med VS alt. VS Code (ser samma fel i VS Code).

Det egentliga felet är att andra template-argumentet till std::array<> måste vara en konstant som kan evalueras vid kompileringstillfället, värdet på thread_count kommer bara vara känt när programmet körs.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Tack till alla som pekade ut felet; har nu bytt ut mot std::vector som jag råddes göra.

Permalänk

Varför ens köra std::array? std::vector är ju alltid bättre på alla punkter.

Permalänk
Medlem
Skrivet av heretic16:

Varför ens köra std::array? std::vector är ju alltid bättre på alla punkter.

I vissa lägen behöver jag inte reducera eller expandera en lista med objekt/värden, därav passar std::array mig. Jag är som sagt nybörjare och lär mig fortfarande. Jag kanske ändrar detta i framtiden men inte nu.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Varför ens köra std::array? std::vector är ju alltid bättre på alla punkter.

Riktigt så enkelt är det inte. Den stora finessen med vector är att man fritt kan ändra storleken, men om det inte är något man behöver kan andra klasser vara bättre (om än bara lite). Vector må vara ett bra standardval, men det är kanske inte alltid det optimala alternativet.

Permalänk
Medlem
Skrivet av Apollo11:

I vissa lägen behöver jag inte reducera eller expandera en lista med objekt/värden, därav passar std::array mig. Jag är som sagt nybörjare och lär mig fortfarande. Jag kanske ändrar detta i framtiden men inte nu.

En god anledning till att använda att std::array där det räcker: innehållet kan allokeras på stacken, medan std::vector växer på heapen. Man sparar alltså minst en minnesallokering på det ibland.