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

时间:2018-10-17 10:18:06

标签: c++

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

#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!"
}

2 个答案:

答案 0 :(得分:13)

这是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;
}

数组引用参数将绑定到字符串文字,而不是指针(可以触发您的宏),推导它们的大小并在函数体中执行检查。然后,如果一切都检查完了,它将返回不变的引用,甚至允许继续进行过载解析。

答案 1 :(得分: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);
}

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