2014-09-25 2 views
1

Я создал шаблон для строк кастинга, делающий разные типы данных, и у него возникают проблемы, когда тип данных является символом unsigned.Вставить std :: string (гарантированный числовой) в unsigned char

template<class TYPE> 
bool TryParse(const std::string value, TYPE &out) 
{ 
    std::istringstream iss(value); 
    iss >> out; 

    if (iss.fail()) 
    { 
     return false; 
    } 

    return true; 
} 

Проблема заключается в istringstream будет относиться к первому символу он видит как полукокс, вместо того, чтобы рассматривать его как числовую строку. Поэтому, если я передаю значение «255», возвращаемое значение будет «2».

Было бы лучшим решением отличить переменную out как unsigned int, выполнить операцию, а затем отбросить назад?

+1

вы можете использовать 'boost :: lexical_cast' - он не касается вашего конкретного вопроса, но он не позволяет вам изобретать колесо. – Chad

+1

Также рассмотрите вопрос об отправке значения 'значение' по ссылке. Как бы то ни было, вы вынуждаете вызывающего абонента копировать строки без уважительной причины. – cdhowie

+0

Почему бы вам просто не добавить специализацию для 'char'? – Deduplicator

ответ

3

Я предлагаю иметь перегрузку, которая относится к unsigned char делам, так как вам нужен промежуточный тип.

bool TryParse(const std::string & value, unsigned char & out) 
{ 
    std::istringstream iss(value); 
    unsigned int i; 
    iss >> i; 

    if (iss.fail()) { return false; } 

    // The less-than-min check is technically redundant because both i and out 
    // are unsigned, but it makes me feel better having it there. It will become 
    // necessary for the "signed char" overload, anyway. 
    if (i > std::numeric_limits<unsigned char>::max() || 
     i < std::numeric_limits<unsigned char>::min()) { 
      throw std::overflow_error(); 
      // Or you could "return false" instead, if that makes more sense. 
    } 

    out = static_cast<unsigned char>(i); 
    return true; 
} 

Вы можете использовать практически идентичную функцию signed char. (Просто замените каждый unsigned на signed.)

Я бы не предложил использовать промежуточный тип в шаблоне, потому что вам нужно будет использовать максимально возможный тип, и не будет ни одного типа, который бы работал. unsigned long long int не совместим, например, с signed long long int, и наоборот, и ни один из этих типов не будет совместим с float или double. Наличие базового шаблона, который использует запрошенный тип напрямую, с перегрузками для проблемных типов (например, char) - это правильный подход.


Обратите внимание, что я изменил параметр value быть ссылки на константные строки, так как это означает, что абонент не требуется, чтобы скопировать строку без причины. Я бы предложил изменить вашу функцию шаблона.

+0

Это прекрасно, спасибо. – JoshBramlett

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