std::enable_if_t 将字符串与非字符串函数参数分开
std::enable_if_t to separate string from non string function parameters
我需要在双引号内打印所有类型的字符串数据,而其他不带双引号的。
这是我检查参数是否为字符串的函数。
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;
}
它没有编译错误
unrecognized template declaration/definition
有人可以告诉我如何解决这个问题或处理这种情况的更好方法吗?
您的代码中有一个不需要的 >(关闭模板类型说明符)
试试这个:
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;
}
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 {};
我需要在双引号内打印所有类型的字符串数据,而其他不带双引号的。
这是我检查参数是否为字符串的函数。
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;
}
它没有编译错误
unrecognized template declaration/definition
有人可以告诉我如何解决这个问题或处理这种情况的更好方法吗?
您的代码中有一个不需要的 >(关闭模板类型说明符)
试试这个:
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;
}
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 {};