std::basic_stringstream<unsigned char> 不会使用 MSVC 10 进行编译

std::basic_stringstream<unsigned char> won't compile with MSVC 10

提问人:Michael J 提问时间:6/18/2012 最后编辑:Michael J 更新时间:6/23/2012 访问量:2033

问:

我正在尝试让 UTF-8 字符与 ANSI 8 位字符共存。我的策略是表示 utf-8 字符,以便可以对这两种字符类型使用适当的函数重载。unsigned char

例如

    namespace MyStuff
    {
        typedef uchar utf8_t;
        typedef std::basic_string<utf8_t> U8string;
    }
    void SomeFunc(std::string &s);
    void SomeFunc(std::wstring &s);
    void SomeFunc(MyStuff::U8string &s);

在我尝试使用字符串流之前,这一切都运行良好。

    std::basic_ostringstream<MyStuff::utf8_t> ostr;
    ostr << 1;

MSVC Visual C++ Express V10 不会编译以下内容:

c:\program files\microsoft visual studio 10.0\vc\include\xlocmon(213): 
    warning C4273: 'id' : inconsistent dll linkage
    c:\program files\microsoft visual studio 10.0\vc\include\xlocnum(65) : 
            see previous definition of 
            'public: static std::locale::id std::numpunct<unsigned char>::id'
    c:\program files\microsoft visual studio 10.0\vc\include\xlocnum(65) : 
            while compiling class template static data member 'std::locale::id 
            std::numpunct<_Elem>::id'
    with
    [
        _Elem=Tk::utf8_t
    ]
    c:\program files\microsoft visual studio 10.0\vc\include\xlocnum(1149) : 
        see reference to function template instantiation 
        'const _Facet &std::use_facet<std::numpunct<_Elem>>(const std::locale &)' 
        being compiled
    with
    [
        _Facet=std::numpunct<Tk::utf8_t>,
        _Elem=Tk::utf8_t
    ]
    c:\program files\microsoft visual studio 10.0\vc\include\xlocnum(1143) : 
        while compiling class template member function 
        'std::ostreambuf_iterator<_Elem,_Traits> 
        std::num_put<_Elem,_OutIt>::
        do_put(_OutIt,std::ios_base &,_Elem,std::_Bool) const'
    with
    [
        _Elem=Tk::utf8_t,
        _Traits=std::char_traits<Tk::utf8_t>,
        _OutIt=std::ostreambuf_iterator<Tk::utf8_t,std::char_traits<Tk::utf8_t>>
    ]
    c:\program files\microsoft visual studio 10.0\vc\include\ostream(295) : 
        see reference to class template instantiation 'std::num_put<_Elem,_OutIt>' 
        being compiled
    with
    [
        _Elem=Tk::utf8_t,
        _OutIt=std::ostreambuf_iterator<Tk::utf8_t,std::char_traits<Tk::utf8_t>>
    ]
    c:\program files\microsoft visual studio 10.0\vc\include\ostream(281) : 
        while compiling class template member function 
        'std::basic_ostream<_Elem,_Traits> &
        std::basic_ostream<_Elem,_Traits>::operator <<(int)'
    with
    [
        _Elem=Tk::utf8_t,
        _Traits=std::char_traits<Tk::utf8_t>
    ]
    c:\program files\microsoft visual studio 10.0\vc\include\sstream(526) : 
        see reference to class template instantiation 
        'std::basic_ostream<_Elem,_Traits>' being compiled
    with
    [
        _Elem=Tk::utf8_t,
        _Traits=std::char_traits<Tk::utf8_t>
    ]
    c:\users\michael\dvl\tmp\console\console.cpp(23) : 
        see reference to class template instantiation 
        'std::basic_ostringstream<_Elem,_Traits,_Alloc>' being compiled
    with
    [
        _Elem=Tk::utf8_t,
        _Traits=std::char_traits<Tk::utf8_t>,
        _Alloc=std::allocator<uchar>
    ]

.

c:\program files\microsoft visual studio 10.0\vc\include\xlocmon(213): 
    error C2491: 'std::numpunct<_Elem>::id' : definition of dllimport 
    static data member not allowed
    with
    [
        _Elem=Tk::utf8_t
    ]

有什么想法吗?

** 编辑于 2012 年 6 月 19 日 **

好吧,我已经更接近理解这一点,但不是如何解决它。

众所周知,静态类变量被定义了两次:

  • 一旦进入类定义和
  • 一旦超出建立存储空间的类定义。

例如

    // in .h file
    class CFoo
    {
        // ...
        static int x;
    };

    // in .cpp file
    int CFoo::x = 42;

现在,在 VC10 标头中,我们得到如下内容:

    template<class _Elem>
    class numpunct : public locale::facet
    {
        // ...
        _CRTIMP2_PURE static locale::id id;
        // ...
    }

当标头包含在应用程序中时,定义为 ,这意味着变量是从 dll 导入的。_CRTIMP2_PURE__declspec(dllimport)

现在,标头还包含以下内容

    template<class _Elem>
    locale::id numpunct<_Elem>::id;

请注意缺少限定符。__declspec(dllimport)

即类声明说变量的静态链接在 dll 中,但对于一般情况,它在 dll 之外声明。id

对于已知的病例,有专业化。

    template locale::id numpunct<char>::id;
    template locale::id numpunct<wchar_t>::id;

它们受 s 保护,因此仅在生成 DLL 时才包含它们。否则,它们将被排除在外。#if

numpunct 的 charwchar_t 版本在 dll 中

因此,我们有类定义说 id 的存储位于 DLL 中,但这仅适用于 和 specialisations,这意味着我的无符号 char 版本注定要失败。:-(charwchar_t

我能想到的唯一方法是创建我自己的专业化:基本上从头文件中复制它并修复它。这引发了许多问题。

有人有更好的主意吗?

C 可视化 C++ Unicode UTF-8 字符串流

评论

0赞 j_kubik 6/18/2012
我认为这里的基本问题是您的 uchars 字符串是 C++ 未知的类型,因此它不知道如何在内部进行到字符串和从字符串转换。你有没有试过只使用类似的东西?这里没有问题,因为不需要转换(如 int->utf8_string),只需附加到内部字符串的末尾。我不知道如何教标准类如何做到这一点,但快速挖掘 C++ 标准至少应该有所帮助。ostr << uchar('a');
0赞 j_kubik 6/18/2012
请注意,诸如“将不起作用”之类的东西(当然,除非您明确定义了此类运算符),并且可能会使编写程序变得更加痛苦。ostr << "Something";
1赞 j_kubik 6/18/2012
请看这里:cplusplus.com/reference/std/locale/numpunct“两个标准专用化定义了 char 和 wchar_t 类型的标准行为。这可能意味着您将不得不提供自己的该课程的专业化,可能还有其他几个课程......
1赞 manasij7479 6/18/2012
基本上,这个:cplusplus.com/reference/string/char_traits afaik。您必须为无符号字符提供相同的信息。有关详细信息,请查看对 unicode 执行此操作的任何库。

答: 暂无答案