c++ - 在编译时或至少在使用之前检查字符串是否包含禁止字符的任何创造性方法?

标签 c++ compile-time static-assert

我需要一种方法来验证常量字符串在编译时不包含特定字符。我考虑过使用 static_assert,但碰壁了,因为我尝试使用 .find 方法,它不是常量。

我可以选择在类的构造函数中进行检查(实例是所述类的 static const 成员)。
但在咬紧牙关之前(因为改变构造函数的行为还有其他影响),我想看看是否有其他人有那些创造性的开箱即用的想法之一仍然可以完成这项工作,最好是在编译时。

最佳答案

常量字符串可能是指字符串文字,因为std::string 不能用在常量表达式中。

在字符串文字的情况下,我们可以利用 constexpr:( Live Demo )

template<int N>
constexpr bool has_forbidden_char(const char (&str) [N], char forbidden)
{
    for(int i = 0; i < N; ++i)
    {
        if (str[i] == forbidden)
            return true;
    }
    return false;
}

int main()
{
    static_assert(!has_forbidden_char("foobar", 'x'));
    static_assert(has_forbidden_char("foobar", 'f'));
}

编辑:如果您假设您只会收到字符串文字而不是任意字符数组,则迭代到 N-1。这样你就不会每次都检查 NULL 字符'\0'。 (C++ 中不存在零长度数组,所以不用担心索引为 -1)

//...
for(int i = 0; i < N-1; ++i){ //...

Edit2:由于您使用的是 Visual Studio 2015,它没有宽松的 constexpr 功能,这里有一个符合 C++11 的有效解决方案:

namespace detail {
  template<int N>
  constexpr bool has_forbidden_char_help(const char(&str)[N], char forbidden, int index)
  {
      return (index < N && (str[index] == forbidden || has_forbidden_char_help(str, forbidden, index+1)));
  }
} // namespace detail

template<int N>
constexpr bool has_forbidden_char(const char (&str) [N], char forbidden)
{
    return detail::has_forbidden_char_help(str, forbidden, 0);
}

int main()
{
    static_assert(!has_forbidden_char("foobar", 'x'), "foobar doesn't have x, so this shouldn't fail...");
    static_assert(has_forbidden_char("foobar", 'f'), "foobar does have f, so this shouldn't fail...");
}

关于c++ - 在编译时或至少在使用之前检查字符串是否包含禁止字符的任何创造性方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46307205/

相关文章:

c++ - 编译时和运行时 (C++) 期间的虚函数和非虚函数

c++ - 这个静态断言能正常工作吗?

c++ - 元组大小默认构造函数及其到 std::size_t 的转换

c++ - g++ 4.7.2 中缺少 std::stoi?

C++ 通过编译时移位来访问基于 1 而不是 0 的数组

C# 固定字符串长度 - 编译时检查

c++ - 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误

c++ - 有什么方法可以静态断言模板参数是不可复制的吗?

c++ - visual studio 2013 在运行.exe 时修改路径变量

c++ - 如何使用 Boost C++ 遍历递归变量 vector