std::string from C style string ctor

In writing a function template having to create a std::string from a char[], I have had to use the following constructor of std::string:

basic_string( CharT const* s, size_type count, Allocator const& alloc = Allocator() );

which you can find documentation for in the standard or on cppreference.com. In using this constructor, I have had a “off by one” problem with the count parameter. The function template I originally wrote used the constructor like this:

template< std::size_t N >
std::string foo( char const ( &char_arr )[N] ) {
   return std::string( char_arr, N );  // WRONG, do not do this
}

which is a mistake. The terminating '\0' character will be included in the value of N and will thus be part of the std::string (which can contain nulls). Thus, the size of the new std::string will be one more then expected:

char const arr[] = "string";
auto bar = foo( arr );
assert( bar.length() != 6 );
assert( bar.length() == 7 );

Usually, when one is certain that the C style string is null terminated, the recommended way to use the constructor is:

std::string the_strg( char_arr, std::strlen( char_arr ) );

Since std::strlen will not include the null terminator in the length returned. To mimic this behavior, my template had to be written as:

template< std::size_t N >
std::string foo( char const ( &char_arr )[N] ) {
   return std::string( char_arr, N - 1 );
}

which will eliminate the need to calculate the length at runtime and yield the correct std::string with the expected length. This is not exactly a hard problem, but it bit me and I want to remember this little detail!


Edit (2018-09-19): Patrice Roy pointed out that my return statement in the first function was awkward (copy pasting and modifying to make an example is not ideal) and the second version was not returning anything. Fixed now. Thanks Patrice for pointing it out.

Invoking a callable in C++

Invoking a callable in C++ This is my exploration of the std::invoke utility of C++17. I started with something vaguely related (which I am discussing here) and ended up reading the standard library implementation of std::invoke (and that of Google’s Abseil library). The funny thing is that in the end, I decided I did not really need any of it for my original motivation, but I did gain some knowledge along the way, so worth the time!

Continue Reading »

Python's range in C++

Exploring loops: Python’s range in C++ In spite of what Sean Parent would like (i.e. no raw loops ;-) ), loops are a common control flow in programming. So common that most languages have more than one loop syntax: for loop, while loop, do while loop… Given their prevalence, loops might seem uninteresting, but when I decided to look into creating a range function[1] for C++ which would behave like Python’s range object, I learned a thing or two and decided to write them down.

Continue Reading »

Mixed types arithmetic in C++

Arithmetic on mixed fundamental types in C++ For a weekend project of mine, I have had to think about mixed type arithmetic on fundamental types in C++. In the process, I made sense of a few fundamental things (no pun intended ;-) ) and I have decided to write them down. Hopefully, writing about it will allow me to both clarify my thoughts and remember the information! Arithmetic conversions Applying binary operators to different types might seem trivial in C++, because it mostly just works.

Continue Reading »

Integer binary representations

Integer binary representations I had never had to look closely at integer binary representations in computers. The mental model I had for them was not wrong, but it turns out it was sub-optimal and there are better ways to do things. If you use high level abstractions and do not mainly work with fundamental types, or if you do not convert between integer types, you do not have to be mindful of the binary representation of integers all the time as you program.

Continue Reading »