1. はじめに
Visual C++ 環境でプログラムしていると std::string
, std::wstring
, CStringA
, CStringW
を使う場面が出てくる。 これらを変換させる個別の関数を作って呼び出していたが 場合分けが 煩わしいので、単純に代入できるクラスを作ってみた。
以下の様な感じで kstring()
を介せば型を気にせず代入可能。
main()
{
string a ;
wstring b ;
CStringA c ;
CStringW d ;
a = kstring(b) ; a = kstring(c) ; a = kstring(d) ;
b = kstring(a) ; b = kstring(c) ; b = kstring(d) ;
c = kstring(a) ; c = kstring(b) ; c = kstring(d) ;
d = kstring(a) ; d = kstring(b) ; d = kstring(c) ;
2. 概要
std::string
を継承する kstring
クラス と std::wstring
を継承する kwstring
クラスを作って、各型からのコンストラクタと 各型へのキャストを定義する。
3. ベースとなる単方向の変換関数
(1) string
→ wstring
inline std::wstring str_to_wstr(std::string const& src)
{
vector<wchar_t> dest( src.length()+16 ) ;
std::size_t converted ;
::mbstowcs_s( &converted, dest.data(), dest.size(), src.c_str(), _TRUNCATE ) ;
return std::wstring( dest.data() ) ;
}
(2) wstring
→ string
inline std::string wstr_to_str(std::wstring const& src)
{
vector<char> dest( src.length()+16 ) ;
std::size_t converted ;
::wcstombs_s( &converted, dest.data(), dest.size(), src.c_str(), _TRUNCATE ) ;
return std::string( dest.data() ) ;
}
4. 変換用のクラス
煩雑になるので CStringA
と CStringW
は後ほど追加。まずは string
と wstring
。
(1) string
の継承クラス kstring
を定義
kstring
に対し、string
, wstring
, kwstring
とのコンストラクタと キャストを定義。
class kwstring ; // wstring の継承クラス
class kstring : public std::string
{
public:
kstring() = default ;
kstring(const string &str) : string(str) { }
kstring(const wstring &wstr)
{
*(string*)this = wstr_to_str( wstr ) ;
}
// kwstring 定義後に記述
inline kstring(const kwstring &kwstr) ;
public:
operator string()
{
return *(string*)this ;
}
operator wstring()
{
return str_to_wstr( *this ) ;
}
// kwstring 定義後に記述
inline operator kwstring() ;
} ;
kstring の kwstring参照部分の定義で、kwstring の後に記述する
inline kstring::kstring(const kwstring &kwstr)
{
*(string*)this = wstr_to_str( kwstr ) ;
}
inline kstring::operator kwstring()
{
return str_to_wstr(*this) ;
}
(2) wstring
の継承クラス
kwstring
に対し、string
, wstring
, kstring
とのコンストラクタと キャストを定義。
class kwstring : public std::wstring
{
public:
kwstring() = default ;
kwstring(const wstring &wstr) : wstring(wstr) { }
kwstring(const string &str)
{
*(wstring*)this = str_to_wstr( str ) ;
}
kwstring(const kstring &kstr)
{
*(wstring*)this = str_to_wstr( kstr ) ;
}
public:
operator wstring()
{
return *(wstring*)this ;
}
operator string()
{
return wstr_to_str( *(wstring*)this ) ;
}
operator kstring()
{
return wstr_to_str(*this) ;
}
} ;
5. CStringA と CStringW に対応
CStringA
と CStringW
は相互代入が可能なのでこれを利用
(1) kstringを拡張する
kstring
に対し、CStringA
, CStringW
とのコンストラクタと キャストを定義。
kstring(const CStringA &str)
{
*(string*)this = (char*)(LPCSTR)str ;
}
kstring(const CStringW &strw)
{
*(string*)this = (char*)(LPCSTR)CStringA(strw) ;
}
operator CStringW()
{
return CStringW( CStringA(this->c_str()) );
}
operator CStringA()
{
return CStringA( this->c_str() ) ;
}
(2) kwstringを拡張する
kwstring
に対し、CStringA
, CStringW
とのコンストラクタと キャストを定義。
kwstring(const CStringW &strw)
{
*(wstring*)this = (wchar_t*)(LPCWSTR)strw ;
}
kwstring(const CStringA &str)
{
*(wstring*)this = (wchar_t*)(LPCWSTR)CStringW(str) ;
}
operator CStringW()
{
return CStringW( this->c_str() ) ;
}
operator CStringA()
{
return CStringA( this->c_str() ) ;
}
6. おまけ
(1) kstring
, kwstring
の出力定義
inline std::ostream & operator << (std::ostream& os, const kstring &str )
{
os << string(str) ;
return os ;
}
inline std::wostream & operator << (std::wostream& os, const kwstring &wstr )
{
os << wstring(wstr) ;
return os ;
}
(2) operator =
を定義すれば 汎用性が増すかな
kstring & operator = (const wstring &wstr)
{
*(string*)this = wstr_to_str( wstr ) ;
return *this ;
}
(3) Windows APIを使った変換
ベースとなる単方向の変換関数を Windows API を使って作った場合
inline std::wstring StringToWString( const std::string &src )
{
vector<wchar_t> dest( src.length()+16 ) ;
::MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, dest.data() ,dest.size() );
return std::wstring( dest.data() ) ;
}
inline std::string WStringToString( const std::wstring &src )
{
vector<char> dest( src.length()+16 ) ;
::WideCharToMultiByte( CP_OEMCP, 0, src.c_str(), -1, dest.data() ,dest.size(), NULL, NULL );
return std::string( dest.data() ) ;
}
7. ソース一括
#include <vector>
#include <iostream>
#include <cstring>
#include <atlstr.h>
using std::string ;
using std::wstring ;
using std::vector ;
using std::cout ;
using std::wcout ;
using std::endl ;
//-------------------------------------
inline std::wstring str_to_wstr(std::string const& src)
{
vector<wchar_t> dest( src.length()+16 ) ;
std::size_t converted ;
::mbstowcs_s( &converted, dest.data(), dest.size(), src.c_str(), _TRUNCATE ) ;
return std::wstring( dest.data() ) ;
}
inline std::string wstr_to_str(std::wstring const& src)
{
vector<char> dest( src.length()+16 ) ;
std::size_t converted ;
::wcstombs_s( &converted, dest.data(), dest.size(), src.c_str(), _TRUNCATE ) ;
return std::string( dest.data() ) ;
}
//-------------------------------------
class kwstring ; // wstring の継承クラス
class kstring : public std::string
{
public:
kstring() = default ;
kstring(const string &str) : string(str) { }
kstring(const wstring &wstr)
{
*(string*)this = wstr_to_str( wstr ) ;
}
inline kstring(const kwstring &kwstr) ;
public:
operator string()
{
return *(string*)this ;
}
operator wstring()
{
return str_to_wstr( *this ) ;
}
inline operator kwstring() ;
public:
kstring(const CStringA &str)
{
*(string*)this = (char*)(LPCSTR)str ;
}
kstring(const CStringW &strw)
{
*(string*)this = (char*)(LPCSTR)CStringA(strw) ;
}
operator CStringW()
{
return CStringW( CStringA(this->c_str()) );
}
operator CStringA()
{
return CStringA( this->c_str() ) ;
}
} ;
//-------------------------------------
class kwstring : public std::wstring
{
public:
kwstring() = default ;
kwstring(const wstring &wstr) : wstring(wstr) { }
kwstring(const string &str)
{
*(wstring*)this = str_to_wstr( str ) ;
}
kwstring(const kstring &kstr)
{
*(wstring*)this = str_to_wstr( kstr ) ;
}
public:
operator wstring()
{
return *(wstring*)this ;
}
operator string()
{
return wstr_to_str( *(wstring*)this ) ;
}
operator kstring()
{
return wstr_to_str(*this) ;
}
public:
kwstring(const CStringW &strw)
{
*(wstring*)this = (wchar_t*)(LPCWSTR)strw ;
}
kwstring(const CStringA &str)
{
*(wstring*)this = (wchar_t*)(LPCWSTR)CStringW(str) ;
}
operator CStringW()
{
return CStringW( this->c_str() ) ;
}
operator CStringA()
{
return CStringA( this->c_str() ) ;
}
} ;
//-------------------------------------
inline kstring::kstring(const kwstring &kwstr)
{
*(string*)this = wstr_to_str( kwstr ) ;
}
inline kstring::operator kwstring()
{
return str_to_wstr(*this) ;
}
//-------------------------------------
inline std::ostream & operator << (std::ostream& os, const kstring &str )
{
os << string(str) ;
return os ;
}
inline std::wostream & operator << (std::wostream& os, const kwstring &wstr )
{
os << wstring(wstr) ;
return os ;
}
//-------------------------------------
int main()
{
string a = "abc" ;
wstring b = L"ABC" ;
CStringA c = "xyz" ;
CStringW d = L"XYZ" ;
a = kstring(b) ; a = kstring(c) ; a = kstring(d) ;
b = kstring(a) ; b = kstring(c) ; b = kstring(d) ;
c = kstring(a) ; c = kstring(b) ; c = kstring(d) ;
d = kstring(a) ; d = kstring(b) ; d = kstring(c) ;
cout << kstring(b) << endl ;
wcout << kstring(a) << endl ;
return 0 ;
}