glades
glades

Reputation: 4848

Idiomatically convert signed to unsigned types if you know that value will be positive

Compare the following code. It's clear from the context that one pointer will always be bigger than the other and the result of std::distance() therefore positive. How do I idiomatically convert from signed to unsigned then without having the compiler complains about narrowing?

Demo

#include <cstdio>
#include <iterator>
#include <string_view>
#include <cstring>

std::string_view foo(const char* token)
{
    const char* first = std::strchr(token, 'H');
    const char* second = std::strchr(first+1, 'W');
    return std::string_view { first, std::distance(first, second) }; // <-- line in question
}

int main()
{
    const char* hello = "Hello World!";
    const auto view = foo(hello);
    printf("%.*s\n", static_cast<int>(view.size()), view.data());
}

Warning:

<source>: In function 'std::string_view foo(const char*)':
<source>:10:51: warning: narrowing conversion of 'std::distance<const char*>(first, second)' from 'std::iterator_traits<const char*>::difference_type' {aka 'long int'} to 'std::basic_string_view<char>::size_type' {aka 'long unsigned int'} [-Wnarrowing]
   10 |     return std::string_view { first, std::distance(first, second) };
      |      

                            ~~~~~~~~~~~~~^~~~~~~~~~~~~~~

Upvotes: 0

Views: 143

Answers (1)

NathanOliver
NathanOliver

Reputation: 180990

The reason you get this error is because you are using list initialization an in that context a narrowing conversion is an error. There are a couple ways to fix this. You can switch from

return std::string_view { first, std::distance(first, second) };

to

return std::string_view(first, std::distance(first, second));

which means you no longer have list initialization and narrowing is no longer considered an error or you can be explicit and use static_cast like

return std::string_view{first, static_cast<std::size_t>(std::distance(first, second))};

Upvotes: 2

Related Questions