【发布时间】:2015-09-19 11:10:34
【问题描述】:
如您所见,我有一个从std::basic_stringstream<typename TString::value_type...> 派生的模板类。尝试转换它们时会出现问题。这可能是一个明显的问题,尽管我似乎无法找到解决方案。
作为main 中的示例,我有一个简单的std::wstring 并使用L"123" 对其进行初始化。
在构造了std::wstring 之后,将调用自定义basic_stringstream 类的运算符(取决于std::wstring 或std::string)。
出于调试目的检查WCStringStream 对象,表明它包含 - 而不是字符串L"123",而是输入字符串的第一个元素的地址。函数 to_bytes 和 from_bytes 确实返回正确的转换字符串,所以剩下的唯一问题是在两个运算符函数中调用运算符:
*this << std::wstring_convert<...>().xx_bytes(s);
示例:
模板类是std::wstring.
输入是std::string。
正在调用&operator<<(const std::string &s)。
字符串已转换。
正在调用&operator<<(const std::wstring &s)。
字符串类型与模板类型匹配。
基类 (basic_stringstream) 的运算符被调用。 (或std::operator...)
结果:
检查:{_Stringbuffer={_Seekhigh=0x007f6808 L"003BF76C췍췍췍췍췍췍췍췍췍...}...}WCStringStream<std::wstring>::str() -> "003BF76C"
预期结果:"123"
这里出了什么问题?
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <codecvt>
template<class TString>
class WCStringStream : public std::basic_stringstream<typename TString::value_type,
std::char_traits<typename TString::value_type>,
std::allocator<typename TString::value_type> >
{
typedef typename TString::value_type CharTraits;
typedef std::basic_stringstream<CharTraits, std::char_traits<CharTraits>, std::allocator<CharTraits> > MyStream;
//more typedefs...
public:
//Constructor...
inline WCStringStream(void) { }
inline WCStringStream(const TString &s) : MyStream(s) { }
//and more...
//operator>> overloads...
//defines for VS2010/2015 (C++11) included
inline WCStringStream &operator<<(const std::wstring &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
return *this;
}
inline WCStringStream &operator<<(const std::string &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
return *this;
}
};
//Example main
int main(int argc, char *argv[])
{
typedef std::wstring fstring;
WCStringStream<std::wstring> ws;
WCStringStream<std::string> ss;
ws << fstring(L"123");
int a = 0;
ws >> a;
std::cout << a << std::endl;
ss << fstring(L"123");
int b = 0;
ss >> b;
std::cout << b << std::endl;
return 0;
}
我目前正在 VS2015 中编译,但我也需要它在 VS2010 上运行。
【问题讨论】:
-
我可以发誓 VS2010/2015 的股票
stringstream已经为你做了这个 -
从您的描述中,我并不完全清楚实际问题是什么。我的第一个想法是你应该看看模板专业化 [cprogramming.com/tutorial/template_specialization.html]
-
@Mgetz 还有
std::stringstream和std::wstringstream,我想将它们与此处未显示的其他功能“结合”起来。 -
typeid(..) == typeid(..)应该是编译时检查吗?因为它目前不是....std::is_same<TString, std::string>::value不是更合适,还是模板专业化? -
可以不使用模板特化,而是将转换接口设为通用,即
std::string convert(std::wstring const&); std::wstring convert(std::string const&);,然后定义两个运算符,例如通过类型函数template<class T> using other_string_type = typename std::conditional<std::is_same<T, std::string>::value, std::wstring, std::string>::type;然后WCStringStream& operator<< (TString const&); WCStringStream& operator<< (other_string_type<TString> const&);
标签: c++ templates c++11 visual-c++ c++03