How to pass tr1 / array to std :: string?

I wonder how to distinguish std::tr1::array<unsigned char, 16> from std::string ?

the compiler always complains, I tried

 std::tr1::array<unsigned char, 16> sss; string(sss); string asd(sss); 

either works ...

+4
source share
2 answers

unsigned char makes this complicated. If you know that your system uses 2s, add 1 byte 8 bits of unsigned char and char , and the implicit conversion from unsigned char to char does what you want (this is not always the case!), And your null array buffer is complete (t .e. characters after the first 0 should be canceled), this function works:

 template<std::size_t N> std::string to_string( std::array<unsigned char, N> const& arr ) { std::string retval; for( auto c : arr ) { if (!c) return retval; retval.push_back(c); } return retval; } 

I have included some paranoia about the possibility that the array may be "complete" and not have a null terminator.

If you really want all 16 unsigned char , even if some of them are null, you want to use this:

 std::string str( arr.begin(), arr.end() ); 

which should use an implicit conversion from unsigned char to char .

If implicit casting does not do what you want, and you know that the memory array is actually a char array, although its type is unsigned char , you need to do some reinterpretation.

For the case with zero completion:

 template<std::size_t N> std::string to_string_helper( const char* buf ) { std::string retval; if (!buf) return retval; for ( const char* it = buf; it < (buf+N); ++it ) { if (!*it) return retval; retval.push_back(*it); } return retval; } template<std::size_t N> std::string to_string_2( std::array<unsigned char, N> const& arr ) { return to_string_helper<N>( arr.data() ); } 

and for the case of "whole buffer":

 template<std::size_t N> std::string to_string_2( std::array<unsigned char, N> const& arr ) { const char* str = reinterpret_cast<const char*>(arr.data()); return std::string( str, str+N ); } 
+5
source

Just to be clear, you know that this cast is a copy transform, right?

 // if you want the whole fixed-size string including any nul characters template <std::size_t N> std::string fixed_array_to_string(std::tr1::array<unsigned char, N> const &array) { return std::string(reinterpret_cast<const char *>(&*array.begin()), N); } // if your array is nul-terminated template <std::size_t N> std::string nul_array_to_string(std::tr1::array<unsigned char, N> const &array) { return std::string(reinterpret_cast<const char *>(&*array.begin())); } 

The &* object is ugly and can be replaced with &array.front() .

You can generalize this to an array of any type if you are sure that interpreting it as char makes sense:

 // if you want the whole fixed-size string including any nul characters template <typename T, std::size_t N> std::string fixed_array_to_string(std::tr1::array<T, N> const &array) { return std::string(reinterpret_cast<const char *>(&*array.begin()), N * sizeof(T)); } 
+2
source

Source: https://habr.com/ru/post/1486292/


All Articles