UTF-8 文字を ANSI 8 ビット文字と共存させようとしています。unsigned char
私の戦略は、関数の適切なオーバーロードを 2 つの文字型に使用できるように、utf-8 文字を表現することでした。
例えば
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 日編集 **
OK、私はこれを理解することに近づきましたが、それを解決する方法はありません.
ご存知のように、静的クラス変数は 2 回定義されます。
- クラス定義で一度、
- ストレージスペースを確立するクラス定義の外に一度。
例えば
// 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;
// ...
}
ヘッダーがアプリケーションに含まれている場合、_CRTIMP2_PURE
は として定義されます__declspec(dllimport)
。これは、変数が dll からインポートされることを意味します。
現在、ヘッダーには次の内容も含まれています
template<class _Elem>
locale::id numpunct<_Elem>::id;
__declspec(dllimport)
修飾子がないことに注意してください。
つまり、クラス宣言は、id
変数の静的リンケージが dll 内にあることを示していますが、一般的なケースでは、変数は dll の外で宣言されます。
既知のケースについては、専門分野があります。
template locale::id numpunct<char>::id;
template locale::id numpunct<wchar_t>::id;
これらは#if
s によって保護されているため、DLL のビルド時にのみ含まれます。それ以外の場合は除外されます。
つまり、numpunct のバージョンchar
とバージョンは dll 内にあります。wchar_t
char
したがって、id のストレージが DLL にあるというクラス定義がありますが、これはおよび特殊化にのみ当てはまりますwchar_t
。つまり、私の unsigned char バージョンは運命づけられています。:-(
私が考えることができる唯一の方法は、独自の専門化を作成することです。基本的には、ヘッダー ファイルからコピーして修正します。これは多くの問題を引き起こします。
誰もがより良いアイデアを持っていますか?