首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何判断C++模板类型是否为C样式字符串

如何判断C++模板类型是否为C样式字符串
EN

Stack Overflow用户
提问于 2014-07-21 05:40:04
回答 4查看 3.9K关注 0票数 21

我正在尝试编写一个模板is_c_str来测试一个类型是否是c样式的字符串。我需要它来尝试编写一个to_string函数,如我这里的另一个问题:Template specialization for iterators of STL containers?所示。

我需要区分c_str和其他类型的指针和迭代器,这样我就可以在表面上表示第一种类型,并将指针/迭代器呈现为不透明的"itor“或"ptr”。代码如下:

代码语言:javascript
复制
#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 *,还可以捕获intdouble。上面的代码输出:

代码语言:javascript
复制
1, 1, 1

(截至gcc-4.8.1)。

我的问题是如何修复is_c_str以正确捕获c风格的字符串?

EN

回答 4

Stack Overflow用户

发布于 2014-07-21 05:55:43

您希望检查类型是否与char *相同,但是您否定了std::is_same的结果,这显然不会产生正确的结果。所以我们把它去掉。

代码语言:javascript
复制
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 *,最简单的解决方案是:

代码语言:javascript
复制
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_referencestd::remove_cv的繁琐,请改用std::decay

代码语言:javascript
复制
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
> {};
票数 22
EN

Stack Overflow用户

发布于 2014-07-21 06:03:54

我试过了,它似乎起作用了:

代码语言:javascript
复制
#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中那么优雅,但另一方面,对于像我这样的笨蛋来说,谓词是一种陌生的语言,而“蛮力”模板专门化在某种程度上更容易理解,并且在这种情况下是可行的,因为专门化很少。

票数 9
EN

Stack Overflow用户

发布于 2014-07-21 07:12:36

已经有一些解决方案,但由于最简单的解决方案真的很简单,因此我将其记在这里。

代码语言:javascript
复制
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 {};
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24855160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档