我正在尝试编写一个模板is_c_str来测试一个类型是否是c样式的字符串。我需要它来尝试编写一个to_string函数,如我这里的另一个问题:Template specialization for iterators of STL containers?所示。
我需要区分c_str和其他类型的指针和迭代器,这样我就可以在表面上表示第一种类型,并将指针/迭代器呈现为不透明的"itor“或"ptr”。代码如下:
#include <iostream>
template<class T>
struct is_c_str
: std::integral_constant<
bool,
!std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};
int main() {
auto sz = "Hello"; //Or: const char * sz = "Hello";
int i;
double d;
std::cout << is_c_str<decltype(sz)>::value << ", "
<< is_c_str<decltype(i)>::value << ", "
<< is_c_str<decltype(d)>::value << std::endl;
}但是,is_c_str不仅可以捕获const char *,还可以捕获int和double。上面的代码输出:
1, 1, 1(截至gcc-4.8.1)。
我的问题是如何修复is_c_str以正确捕获c风格的字符串?
发布于 2014-07-21 05:55:43
您希望检查类型是否与char *相同,但是您否定了std::is_same的结果,这显然不会产生正确的结果。所以我们把它去掉。
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};但是,这将导致输出0, 0, 0。现在的问题是,remove_cv删除了顶级的简历限定符,但char const *中的const不是顶级的。
如果您想同时匹配char *和char const *,最简单的解决方案是:
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value ||
std::is_same<char const *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};以上版本仍然与char[]不匹配。如果您也想匹配它们,并减少组合std::remove_reference和std::remove_cv的繁琐,请改用std::decay。
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char const *, typename std::decay<T>::type>::value ||
std::is_same<char *, typename std::decay<T>::type>::value
> {};发布于 2014-07-21 06:03:54
我试过了,它似乎起作用了:
#include <iostream>
template<class T>
struct is_c_str : std::integral_constant<bool, false> {};
template<>
struct is_c_str<char*> : std::integral_constant<bool, true> {};
template<>
struct is_c_str<const char*> : std::integral_constant<bool, true> {};
int main() {
auto sz = "Hello";
int i;
double d;
std::cout << is_c_str<decltype(sz)>::value << ", "
<< is_c_str<decltype(i)>::value << ", "
<< is_c_str<decltype(d)>::value << std::endl;
}显然,枚举每个案例并不像将通用谓词放在std:integral_constant中那么优雅,但另一方面,对于像我这样的笨蛋来说,谓词是一种陌生的语言,而“蛮力”模板专门化在某种程度上更容易理解,并且在这种情况下是可行的,因为专门化很少。
发布于 2014-07-21 07:12:36
已经有一些解决方案,但由于最简单的解决方案真的很简单,因此我将其记在这里。
template< typename, typename = void >
struct is_c_str
: std::false_type {};
template< typename t >
struct is_c_str< t *,
typename std::enable_if< std::is_same<
typename std::decay< t >::type,
char
>::value >::type
>
: std::true_type {};https://stackoverflow.com/questions/24855160
复制相似问题