在编译时检查字符串字面量的长度

16

我希望在编译时检查我的字符串文字的长度。目前我正在考虑以下结构,但无法完成它:

我想要在编译时检查字符串文字的长度。目前我在考虑下面的结构,但是无法完成它:

#define STR(s) (sizeof(s) < 10 ? s : /* somehow perform static_assert */)

void foo(const char* s) {}
int main() { 
    foo(STR("abc")); // foo("abc")
    foo(STR("abcabcabcabc")); // compile time error: "String exceeds 10 bytes!"
}

你想要这个吗:#define STR(s) (strlen(s) < 10 ? s : nullptr)?那么在foo函数内部检查“空值”... - Ruks
3
为什么会导致编译时错误? - StoryTeller - Unslander Monica
@StoryTeller 哦,那只在代码的注释中描述了,其他地方没有,我明白了... - Ruks
@Ruks 还有标题和第一句话。 - molbdnilo
你可以将字符串字面量声明为 const char 数组,然后使用 sizeof() -1 - Thomas Matthews
2个回答

20
这里讲的是C++,与宏相比,有更好的选择。模板可以给你想要的精确语义。
template<std::size_t N>
constexpr auto& STR(char const (&s)[N]) {
    static_assert(N < 10, "String exceeds 10 bytes!");
    // < 11 if you meant 10 characters. There is a trailing `\0`
    // in every literal, even if we don't explicitly specify it
    return s;
}

数组引用参数将绑定到字符串字面值,而不是指针(可能会导致宏错误),推断它们的大小,并在函数体中执行检查。然后,如果一切都符合要求,它将返回未更改的引用,甚至允许继续重载解析。


@Ruks - 关于 C++ 和 C 标签的普遍共识是,除非另有说明,否则我们假定使用最新的标准。而且现在已经是2018年了,除非OP要求,否则不再需要添加C++1z免责声明。 - StoryTeller - Unslander Monica
至于“不起作用”,除了constexpr之外,其他所有东西都只是C++03可以执行或模拟的便利功能。 - StoryTeller - Unslander Monica

1
我会补充@StoryTeller - Unslander Monica的优秀答案, 如果你需要(像我一样)传递一个字符串的最大长度参数,你可以扩展实现使其更通用:
template<const int MAX_LEN, std::size_t N>
constexpr auto& STR(char const (&s)[N]) 
{
    static_assert(N < MAX_LEN, "String overflow!");
    return s;
}

如果您需要多个已知长度,可以使用模板特化:

template<std::size_t N>
constexpr auto & STR16(char const (&s)[N])
{
    return STR<16>(s);
}

第一个函数可以是通用版本,而第二个函数可以访问项目中的常量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接