【问题标题】:How do I differentiate between a char[3] and a string literal with three characters?如何区分 char[3] 和具有三个字符的字符串文字?
【发布时间】:2014-04-12 21:06:28
【问题描述】:

如果我调用这个函数:

template <typename t>
size_t
Foo(const T& str) {
  return std::distance(std::begin(str), std::end(str));
}

...这三种类型:

const auto a = "abc";
const char b[3] = {'a', 'b', 'c'};
const std::string c("abc");

第一种类型会返回 4(包括 null),其他类型返回 3。如何区分这些类型,使它们都返回 3(字符数也是如此)?

【问题讨论】:

  • 很遗憾,您无法将字符串文字与任何其他 const chars 数组区分开来。这是语言的限制。
  • 例如,您可以检查最后一个字符是否为'\0'(对于char 的数组)。这当然会扩展到数组中任意位置的'\0'
  • @KerrekSB constexpr 允许在编译时检查最后一个字节,但这不考虑 1) 当字符串转换为 char * 时,或 2) 当它包含一个内部 NUL 字节。
  • @Potatoswatter:没错。换句话说,您通常无法将字符串文字与 const-char 数组区分开来:-S

标签: templates c++11 generic-programming


【解决方案1】:

字符串文字"abc" 包含一个空终止符字节。 a 的声明就好像是一样的

char a[] = { 'a', 'b', 'c', '\0' };

如果您不想计算终止符或后面的字符,您可以使用std::strlen。但是,这依赖于该字节的存在,并且在给定b 时可能会崩溃。你可以做一个重载集:

template< typename t >
std::size_t string_length( t const & s ) {
    return s.size();
}

std::size_t string_length( char const * s ) { // requires a termination byte!
    return std::strlen( s );
}

template< std::size_t n > // requires the name of the array to be passed!
std::size_t string_length( char const (&s)[n] ) {
    return std::find( &* s, s + n, '\0' ) - s;
}

然而,这是一种非常危险的做法,因为如果将 b 数组分配给 char * 变量,该变量将选择第二个重载,但缺少终止符字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2011-09-23
    • 1970-01-01
    相关资源
    最近更新 更多