2013-06-14 4 views
4

Интересно, как отливать std::tr1::array<unsigned char, 16> в std::string?как передать tr1/array в std :: string?

компилятор всегда жалуются, я пытался

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

либо делает работу ...

ответ

5

unsigned char делает это сложно. Если вы знаете, что ваша система использует 2s дополнение 1 байт 8 бит unsigned char и char, а неявное преобразование с unsigned char в char делает то, что вы хотите (это не всегда так!), И ваш буфер массива имеет нулевое завершение (т.е. символы после первый 0 один должны быть отброшено), эта функция работает:

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; 
} 

Я включил некоторую паранойю о возможности того, что массив может быть «полным» и отсутствовать нулевой терминатор.

Если вы на самом деле хотите все 16 unsigned char, даже если некоторые из них нулю, вы будете хотеть использовать это:

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

, который следует использовать неявное преобразование из unsigned char в char.

Если неявное приведение не делает то, что вы хотите, и вы знаете, что память array «s фактически массив char, даже если его тип unsigned char, что вам нужно сделать некоторые переинтерпретировать литье.

Для нуля случая:

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()); 
} 

и для «всего буфера» случая:

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); 
} 
+0

+1 за второй вариант, но первый не будет, если компилировать 'sss' - массив' unsigned char'. –

+0

@AndyProwl Пропустил этот 'unsigned'. Уточнено. Я думаю, что я получил неопределенные биты поведения правильно, но не уверен. – Yakk

+0

@AndyProwl - также не будет компилироваться, если 'sss' является массивом' signed char'. Работает только 'char'. –

2

Просто чтобы быть ясно, вы знаете, это приведение является копированием преобразования, не так ли?

// 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())); 
} 

&* вещь безобразна, и может быть заменен &array.front().

Вы можете обобщить это массив любого типа, если вы уверены, интерпретируя его как char имеет смысл:

// 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)); 
} 
+0

Разве разыменование итератора 'end' закончено? И я думаю, что '(begin, end)' ctor 'std :: string' копирует нулевые байты? – Yakk

+0

Всего секунду, я перенес какую-то катастрофическую потерю мозга там ... – Useless

Смежные вопросы