не может извлечь двойное значение из строки, нечувствительной к регистру?

Я пытаюсь придумать строку без учета регистра, и я нашел следующее в Интернете

http://www.gotw.ca/gotw/029.htm

Итак, в основном мой код для создания строки без учета регистра выглядит следующим образом

struct ci_char_traits : public std::char_traits<char> {

    static bool eq( char c1, char c2 )
    { return toupper(c1) == toupper(c2); }

    static bool ne( char c1, char c2 )
    { return toupper(c1) != toupper(c2); }

    static bool lt( char c1, char c2 )
    { return toupper(c1) <  toupper(c2); }

    static int compare(const char* s1, const char* s2, size_t n )
    { return memicmp( s1, s2, n ); }

private:
    static int memicmp(const void *s1, const void *s2, size_t n) {

        if (n != 0) {
            const unsigned char *p1 = (const unsigned char *)s1, *p2 = (const unsigned char *)s2;
            do {
                if (toupper(*p1) != toupper(*p2))
                    return (*p1 - *p2);
                p1++;
                p2++;
            } while (--n != 0);
        }
        return 0;
    }
};

// case insensitive string type definition
typedef std::basic_string<char, ci_char_traits> ci_string;

// provide standard output for case insensitive string
template<typename char_type, typename traits_type, typename allocator_type>
inline std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& os,
           const std::basic_string<char_type, ci_char_traits, allocator_type>& str) {
    return std::__ostream_insert(os, str.data(), str.size());
}

поэтому определение типа - это строка. Теперь проблема, которая у меня есть, заключается в том, что я не могу заставить функцию работать с этой пользовательской строкой, поскольку она работает с обычной строкой. Следующая функция шаблона получает значение из строки, но

template <typename T, class string_type, typename counter_type>
T stream_cast(const string_type& s) {

  typedef typename string_type::value_type char_type;
  typedef typename string_type::traits_type traits_type;

  typename std::basic_istringstream<char_type, traits_type> iss(s);

  T x;
  char c;
  if (!(iss >> x) || iss.get(c))
     cout<<"*** ERROR *** Bad Conversion!"<<endl;
  return x;
} 

Я вызываю эту функцию, чтобы получить двойное значение из строки следующим образом:

ci_string str("2.0");
double test = stream_cast<double>(str);

Но что-то не так с моим определением строки без учета регистра, потому что оценка объекта потока через оператор! всегда терпит неудачу (строка !(iss >> x) всегда верна для этого типа строки).

Кто-нибудь знает, почему у меня возникла эта проблема? Заранее спасибо, что нашли время прочитать этот длинный пост.

aa


person aaragon    schedule 09.10.2011    source источник
comment
Я предполагаю, что все основные операции форматирования определены только для char_traits<char>, поэтому этих перегрузок просто не существует. Вы можете обойти это, используя обычные строки для ввода-вывода и просто создавая одну строку из другой (например, ci_string is(s.begin(), s.end()); и т. д.).   -  person Kerrek SB    schedule 09.10.2011
comment
Интересно: код, скомпилированный с помощью VC++ 2010, работает, как и ожидалось, но при компиляции с помощью gcc 4.5.3 возникает описанная выше проблема.   -  person Eugene    schedule 09.10.2011
comment
Я просто потратил еще 2 часа, пытаясь выяснить, почему это происходит. Badbit установлен для этого типа строки, но я понятия не имею, почему. Я попытался написать свою версию функции basic_istream‹_CharT, _Traits›::_M_extract, но в какой-то момент остановился, потому что не смог получить доступ к защищенным членам класса basic_istream. Это сводит меня с ума... =/   -  person aaragon    schedule 10.10.2011


Ответы (1)


Вы написали собственный оператор вывода "оператор>>", но не оператор ввода "оператор‹‹", и это то, что вам нужно.

Это отлично работает:

ci_string str("2.0");
std::cout << str << std::endl;

из-за оператора>>.

Но

std::cin >> str

не.

person Marshall Clow    schedule 10.11.2011
comment
Спасибо, Маршалл, за ответ. Я попытаюсь вернуться к этому фрагменту кода и добавить оператор. Сам бы я в этом не разобрался. - person aaragon; 19.01.2012