我需要在双引号内打印所有类型的字符串数据,而其他字符串数据不需要双引号。
这是我检查参数是否为字符串的函数。
template<class T>
struct is_str : std::integral_constant<bool, false> {};
template<> struct is_str<char*> : std::integral_constant<bool, true> {};
template<> struct is_str<wchar_t*> : std::integral_constant<bool, true> {};
template<> struct is_str<const char*> : std::integral_constant<bool, true> {};
template<> struct is_str<const wchar_t*> : std::integral_constant<bool, true> {};
template<> struct is_str<std::string> : std::integral_constant<bool, true> {};
template<> struct is_str<const std::string> : std::integral_constant<bool, true> {};
template<> struct is_str<std::wstring> : std::integral_constant<bool, true> {};
template<> struct is_str<const std::wstring> : std::integral_constant<bool, true> {};
在打印机功能中,我使用上述功能
template<typename T>
std::enable_if_t<is_str<T>::value>, std::ostream&>
operator<<(std::ostream& xx, const T& ar)
{
xx << "\"" << ar << "\"";
return xx;
}
template<typename T>
std::enable_if_t<!is_str<T>::value>, std::ostream&>
operator<<(std::ostream& xx, const T& ar)
{
xx << ar;
return xx;
}
它没有使用错误
进行编译无法识别的模板声明/定义
有人可以告诉我如何解决这个或更好的方法来处理这种情况吗?
答案 0 :(得分:3)
Graham Best是对的,但还有另一个(更大的,恕我直言)问题。
你没有定义operator<<
;你正在重新定义它自称。
据我所知,这是不可能的(你重新定义一个函数,编译器不知道哪个版本调用)和你何时编写(在重新定义的运算符内)
xx << "\"" << ar << "\"";
应该使用哪个版本的operator<<()
?新重新定义(导致循环递归)或旧的?
我认为退出此问题的最佳方法是避免重新定义operator<<()
并定义一个简单的函数;例如,以下print()
template<typename T>
std::enable_if_t<is_str<T>::value, std::string> print (T const & ar)
{
std::ostringstream oss;
oss << "\"" << ar << "\"";
return oss.str();
}
template<typename T>
std::enable_if_t<!is_str<T>::value, T const &> print (T const & ar)
{ return ar; }
并以这种方式使用
std::cout << print(std::string{"abc"}) << std::endl; // add quotes
std::cout << print(1) << std::endl; // no quotes
En passant:有几个类可用于编写更紧凑的代码:std::true_type
,定义为std::integral_constant<bool, true>
,std::false_type
定义为std::integral_constant<bool, false>
}。
因此,您可以按如下方式定义is_str
template<class T>
struct is_str : std::false_type {};
template<> struct is_str<char*> : std::true_type {};
template<> struct is_str<wchar_t*> : std::true_type {};
// ...
OBSERVE ,如果你写
std::cout << print("abc") << std::endl; // add quotes
print()
不会添加引号。
这是因为"abc"
不是char const *
;这是一个const char[4]
。
因此,如果您想要将引号添加到char[N]
和wchar_t[N]
,则应添加以下特色
template<std::size_t N> struct is_str<char[N]> : std::true_type {};
template<std::size_t N> struct is_str<wchar_t[N]> : std::true_type {};
答案 1 :(得分:1)
你有一个不受欢迎的&gt;在您的代码中(关闭模板类型说明符)
试试这个:
template<class T>
struct is_str : std::integral_constant<bool, false> {};
template<> struct is_str<char*> : std::integral_constant<bool, true> {};
template<> struct is_str<wchar_t*> : std::integral_constant<bool, true> {};
template<> struct is_str<const char*> : std::integral_constant<bool, true> {};
template<> struct is_str<const wchar_t*> : std::integral_constant<bool, true> {};
template<> struct is_str<std::string> : std::integral_constant<bool, true> {};
template<> struct is_str<const std::string> : std::integral_constant<bool, true> {};
template<> struct is_str<std::wstring> : std::integral_constant<bool, true> {};
template<> struct is_str<const std::wstring> : std::integral_constant<bool, true> {};
template<typename T>
std::enable_if_t<is_str<T>::value, std::ostream&> /* fixed line versus yours */
operator<<(std::ostream& xx, const T& ar)
{
xx << "\"" << ar << "\"";
return xx;
}
template<typename T>
std::enable_if_t<!is_str<T>::value, std::ostream&> /* fixed line versus yours */
operator<<(std::ostream& xx, const T& ar)
{
xx << ar;
return xx;
}