c++ - 来自模板参数的字符串的 constexpr 长度

标签 c++ string c++11 templates string-length

我正在尝试使用 C++11 获取作为模板参数传递的字符串的长度。到目前为止,这是我发现的内容:

#include <iostream>
#include <cstring>
extern const char HELLO[] = "Hello World!!!";

template<const char _S[]>
constexpr size_t len1() { return sizeof(_S); }

template<const char _S[]>
constexpr size_t len2() { return std::strlen(_S); }

template<const char _S[], std::size_t _Sz=sizeof(_S)>
constexpr size_t len3() { return _Sz-1; }

template<unsigned int _N>
constexpr size_t len5(const char(&str)[_N])
{
    return _N-1;
}

int main() {
    enum {
        l1 = len1<HELLO>(),
        // l2 = len2<HELLO>() does not compile
        l3 = len3<HELLO>(),
        l4 = len3<HELLO, sizeof(HELLO)>(),
        l5 = len5(HELLO),
    };
    std::cout << l1 << std::endl;  // outputs 4
    // std::cout << l2 << std::endl;
    std::cout << l3 << std::endl; // outputs 3
    std::cout << l4 << std::endl; // outputs 14
    std::cout << l5 << std::endl; // outputs 14
    return 0;
}

我对结果不是很惊讶,我知道数组的大小在 len1() 和 len2() 的情况下丢失了,尽管信息在编译时存在。

有没有办法将有关字符串大小的信息也传递给模板?像这样的东西:

template<const char _S[unsigned int _N]>
constexpr size_t len6() { return _N-1; }

[根据上下文和意图进行编辑] 我放弃了在编译时连接一组字符串的尝试,所以我尝试在初始化时进行连接。写类似 a().b().c().str() 的东西会输出 "abc"同时 a().b().str()会输出 "ab"

使用模板,a().b()创建一个类型 B与父类型 A . a().b().c()创建类型 C与父类型 B它有一个父类型 A

给定一个类型 B和 parent 一起A ,这是一个独特的类型,它可以有自己的静态缓冲区来保存连接(这就是为什么 l5 对我不利)。然后我可以在静态缓冲区中连续地对每一个进行 strcpy。我不想使用动态分配的缓冲区,因为此时我的分配器不一定已配置。

该缓冲区的大小应足以容纳与 A 关联的字符串以及与 B 关联的字符串是我想弄清楚的。如果我明确地将 sizeof() 作为额外的模板参数(如上面代码片段中的 l4 所做的那样),我可以让它工作,但这会使整个代码难以阅读且使用起来很麻烦。


[编辑 2] 我标记了最有帮助的答案 - 但 Yakk 的答案在 gcc 上也很好,但它没有用 Visual Studio 编译。

我目前的理解是我们不能依赖 const char []用外部链接来提供它们的大小。它可能在本地工作(如果模板是在与符号相同的单元中编译的),但如果 const char[] 则它不会工作。位于要在多个地方使用的头文件中。

所以我放弃了尝试从 const char* 模板参数中提取长度并决定使用 l4 sizeof()在哪里也提供给模板参数。

对于那些好奇整个事情结果如何的人,我在 ideone 上粘贴了一个完整的工作示例:http://ideone.com/A0JwO8

我现在可以写 Path<A>::b::c::path()并得到对应的"b.c"初始化时静态缓冲区中的字符串。

最佳答案

constexpr std::size_t length( const char * str ) {
  return (!str||!*str)?0:(1+length(str+1));
}

template<const char * String>
constexpr size_t len() { return length(String); }

extern constexpr const char HELLO[] = "Hello World!!!";

live example . C++14 中不需要递归。

关于c++ - 来自模板参数的字符串的 constexpr 长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40179625/

相关文章:

c++ - c++11 中的模板化 union

c++ - 如何为用户定义的类实现 c++11 move 函数?

c++ - 重新定义派生类的变量

使用 "libstudxml"库的 C++ 代码无法编译或链接

Python如何提取pandas数据框中[]括号内的指定字符串并使用 bool 值创建一个新列

linux shell 脚本 : getting filename from a user input string

java - 将字符串分成子字符串,将它们转换为整数,并将它们分配给实例变量

c++ - 为什么 C++ 标准库没有具有连续内存的双端队列版本?

c++ - 输出吐出两个额外的控制字符,可能是内存损坏错误?

c++ - 如何为特定构建配置生成 Doxygen 文档