如何判断C模板类型是否为C型字符串

我试图写一个模板is_c_str来测试一个类型是一个c风格的字符串。我需要这个尝试写一个to_string函数,如我的另一个问题所示:
How to write template specialization for iterators of STL containers

我需要告诉c_str和其他类型的指针和迭代器,以便我可以在face值中表示第一个,并将指针/迭代器渲染为不透明的“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风格的字符串?

最佳答案
你想检查类型是否与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删除顶级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
> {};

转载注明原文:如何判断C模板类型是否为C型字符串 - 代码日志