C ++: Есть ли хороший способ чтения / записи без указания типа символов в именах функций? (cout против wcout и т. д.) - PullRequest
4 голосов
/ 17 марта 2010

У меня проблема с получением программы для чтения из файла на основе шаблона, например:

bool parse(basic_ifstream<T> &file)
{
    T ch;
    locale loc = file.getloc();
    basic_string<T> buf;
    file.unsetf(ios_base::skipws);
    if (file.is_open())
    {
        while (file >> ch)
        {
            if(isalnum(ch, loc))
            {
                buf += ch;
            }
            else if(!buf.empty())
            {
                addWord(buf);
                buf.clear();
            }
        }
        if(!buf.empty())
        {
            addWord(buf);
        }
        return true;
    }
    return false;
}

Это будет работать, когда я создаю экземпляр этого класса с <char>, но возникают проблемы, когда я использую <wchar_t> (явно).

Вне класса я использую:

for (iter = mp.begin(); iter != mp.end(); ++iter )
{
    cout << iter->first << setw(textwidth - iter->first.length() + 1);
    cout << " " << iter->second << endl;
}

Чтобы записать всю информацию из этой структуры данных (это map<basic_string<T>, int>), и, как и предсказывалось, cout взрывается, если iter->first не является массивом char.

Я посмотрел онлайн, и единодушным является использование wcout, но, к сожалению, поскольку эта программа требует, чтобы шаблон мог быть изменен во время компиляции (<char> -> <wchar_t>), я не уверен, как я мог сойти с рук, просто выбрав cout или wcout. То есть, если не существует способа чтения / записи широких символов без изменения большого количества кода.

Если это объяснение звучит неловко сложно, дайте мне знать, и я рассмотрю его как можно лучше.

Ответы [ 2 ]

6 голосов
/ 17 марта 2010

Используйте класс черт. Вместо того чтобы ссылаться непосредственно на код cout в коде, вы должны ссылаться на traits<T>::cout, а затем специализировать traits<char> на std :: cout и traits<wchar_t> на wcout.

Обновлено

template <typename T>
class traits {
public:
    static std::basic_ostream<T>& tout;
};

template<>
std::ostream& traits<char>::tout = std::cout;

template<>
std::wostream& traits<wchar_t>::tout = std::wcout;

int _tmain(int argc, _TCHAR* argv[])
{
    traits<char>::tout<<"Ascii";
    traits<wchar_t>::tout<<L"Unicode";
    return 0;
}
0 голосов
/ 17 марта 2010

Конечно, просто переопределите шаблоны и используйте typedef:

#ifdef USE_UNICODE
typedef wchar_t tchar_t
#else
typedef unsigned char tchar_t
#endif

Затем вы можете использовать шаблоны большинства стандартных функций / контейнеров C ++:

typedef std::basic_string<tchar_t> tstring

и т.д.

...