Bil*_*eal 4 c++ unicode templates iostream
我正在为我的一类实现一个流插入运算符.我希望我的班级可以同时使用窄流和宽流.我正在使用模板来允许这种行为 - 除了字符文字之外,所有内容都与实际使用的流类型无关.如果它是一个宽字符串,字符文字需要L预先添加到文字中,否则它们不会.
有没有办法将这种事情键入模板参数,这样我就不需要复制这么多代码?
(如果可能的话,我宁愿避免在运行时执行从窄到宽的字符或从宽到窄的字符转换.)
我目前拥有的示例 - 它是一个模板,但由于字符文字宽,它不适用于窄字符流:
template <typename charT, typename traits>
std::basic_ostream<charT, traits>& operator<<(
    std::basic_ostream<charT, traits>& lhs,
    const Process& rhs
    )
{
    lhs << L"Process (0x" << std::setw(8) << std::hex
        << std::setfill(L'0') << rhs.GetId() << L") ";
    lhs << rhs.GetName() << std::endl;
    lhs << L"Command Line: " << rhs.GetCmdLine() << std::endl;
    const std::vector<Thread>& threads = rhs.GetThreads();
    for (std::vector<Thread>::const_iterator it = threads.begin(); 
        it != threads.end(); ++it)
    {
        lhs << L" --> " << *it << std::endl;
    }
    const std::map<void *, Module>& modules = rhs.GetModules();
    for (std::map<void *, Module>::const_iterator it = modules.begin(); 
        it != modules.end(); ++it)
    {
        lhs << L" --> " << it->second << std::endl;
    }
    return lhs;
}
如果你不想要运行时开销,我认为,虽然很丑,但在这种情况下,宏可以帮助你.
template <typename T>
inline const T* select(const char* narrow, const wchar_t* wide);
template <>
inline const char* select<char>(const char* narrow, const wchar_t* /*wide*/)
{
    return narrow;
}
template <>
inline const wchar_t* select<wchar_t>(const char* /*narrow*/, const wchar_t* wide)
{
    return wide;
}
#define doselect(T, str) select<T>(str, L ## str)
template <typename charT, typename traits>
std::basic_ostream<charT, traits>& operator<<(
    std::basic_ostream<charT, traits>& lhs,
    const Process& rhs
    )
{
    lhs << doselect(charT, "Process (0x") << std::setw(8) << std::hex
        << std::setfill(charT('0')) << rhs.GetId() << doselect(charT, ") ");
    lhs << rhs.GetName() << std::endl;
    lhs << doselect(charT, "Command Line: ") << rhs.GetCmdLine() << std::endl;
    const std::vector<Thread>& threads = rhs.GetThreads();
    for (std::vector<Thread>::const_iterator it = threads.begin(); 
        it != threads.end(); ++it)
    {
        lhs << doselect(charT, " --> ") << *it << std::endl;
    }
    const std::map<void *, Module>& modules = rhs.GetModules();
    for (std::map<void *, Module>::const_iterator it = modules.begin(); 
        it != modules.end(); ++it)
    {
        lhs << doselect(charT, " --> ") << it->second << std::endl;
    }
    return lhs;
}
您可以doselect使用另一个漂亮的宏进行扩展,以进一步减少代码重复.即doselect2(" --> ")会自动扩展到doselect(charT, " --> ").