What is the best way to convert from a std::array<char, N> to a std::string?
I have tried producing a template method but have had no luck. I think my C++ skills just aren't up to scratch. Is there an idiomatic way of doing this in C++?
I won't say it is the "best way", but a way is to use std::string's iterator constructor:
std::array<char, 10> arr;
... // fill in arr
std::string str(std::begin(arr), std::end(arr));
std::array also has begin and end as member functions.std::string(arr.begin(), arr.end()). Too late.std::begin and std::end are meant to be super-generic, because they work on built-in arrays, as well as anything with begin() and end() member functions.If there is a null terminated string in the array so:
std::array<char, 4> arr = {'a','b','c',0};
std::string str(arr.data());
string(const char* s, size_t n); which seems to work even without a null terminator.The following implementation will produce a std::string of the input that ends at either the first null-termination or the full array length, whichever comes first:
template<size_t Size>
inline std::string ToString(const std::array<char, Size>& input)
{
const auto& safeLength = GetStringLength(input.data(), Size);
return std::string(input.data(), safeLength);
}
You can use a compiler-provided strnlen_s() instead of GetStringLength(), if you have it, otherwise the implementation would be:
inline constexpr size_t GetStringLength(const char* input, size_t maximumLength)
{
size_t length = 0;
for (; length < maximumLength && input && input[length]; length++) {}
return length;
}
This recommended implementation is likely slightly slower but is the safest and likely most desired.
Using the return std::string(input.data()); method (without taking a length) would be unsafe if the input is not null-terminated, and using return std::string(std::begin(arr), std::end(arr)); would include any nulls or cruft data in the input array.
The following inputs may fail for the other suggested implementations:
std::array<char, 10> array1 = {'a','b','c'};
std::array<char, 3> array2 = {'a','b','c'};
Using the implementation in this answer, array1 may create a std::string of size 10 filled with 7 nulls at the end, which may be unexpected.
Using the implementation in this answer, array2 would likely overflow and read in random cruft data!