Конвертировать std::string в ci_string

Я использовал этот подход для создания нечувствительного к регистру typedef для строки. Теперь я пытаюсь преобразовать std::string в ci_string, Все следующие ошибки:

std::string s {"a"};
ci_string cis {s};
ci_string cis (s);
ci_string cis {(ci_string)s};
ci_string cis ((ci_string)s);
ci_string cis = s;

Я потратил некоторое время, пытаясь понять, как перегрузить = оператор, и я попытался использовать static_cast а также dynamic_cast безуспешно. Как я могу это сделать?

2 ответа

Решение

У вас два разных типа, поэтому вы не можете использовать конструктор с обычным std::string, Но ваша строка все еще может копировать строку C, так что это должно работать:

std::string s{"a"};
ci_string cis{ s.data() }; // or s.c_str(), they are the same

std::string а также ci_string несвязанные типы. Почему бы static_cast или же dynamic_cast быть в состоянии преобразовать их? Помните: два разных экземпляра одного и того же шаблона являются несвязанными типами и потенциально полностью несовместимы.

Откажись от идеи перегрузки operator= или на какую-то магию, которая выполняет преобразование автоматически. У вас есть два несвязанных типа. Но оба они предлагают функции-члены, которые вы можете успешно использовать для копирования char элементы от одного к другому.

Просто напишите простую функцию преобразования, которая использует тот факт, что оба std::string а также ci_string иметь их value_type определяется как charи, соответственно, использовать один из std::basic_string конструкторы, либо тот, который принимает указатель на необработанные данные, либо тот, который принимает два итератора, которые образуют диапазон.

Вот полный пример:

#include <string>
#include <iostream>

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) {
        while( n-- != 0 ) {
            if( toupper(*s1) < toupper(*s2) ) return -1;
            if( toupper(*s1) > toupper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a) {
        while( n-- > 0 && toupper(*s) != toupper(a) ) {
            ++s;
        }
        return s;
    }
};

typedef std::basic_string<char, ci_char_traits> ci_string;

ci_string to_ci_string(std::string const& src)
{
    return ci_string(src.begin(), src.end());
    // or:
    // return ci_string(src.c_str());
}

int main()
{
    std::string s {"a"};
    auto cis = to_ci_string(s);

    std::cout << cis.c_str() << "\n";
}
Другие вопросы по тегам