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

See*_*per 1 c++ static-assert compile-time

我需要一种方法来验证常量字符串在编译时不包含某个字符.我想过使用static_assert,但是碰到了一堵砖墙,因为我正在尝试使用.find方法,它不是常量.

我可以选择在类的构造函数中进行检查(实例是static const所述类的成员).
但是在咬住子弹之前(因为改变构造函数的行为还有其他含义),我想看看是否还有其他人有一个创造性的开箱即用的想法仍然可以完成,最好是在编译时.

And*_*dyG 5

通过常量字符串,您可能意味着字符串文字,因为std::string不能在常量表达式中使用.

在字符串文字的情况下,我们可以利用constexpr:( 现场演示)

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'));
}
Run Code Online (Sandbox Code Playgroud)

编辑:N-1如果您假设您只接收字符串文字而不是任意字符数组,则迭代到.这样,您每次都不会检查NULL字符'\ 0'.(C++中不存在零长度数组,因此不必担心-1处的索引)

//...
for(int i = 0; i < N-1; ++i){ //...
Run Code Online (Sandbox Code Playgroud)

Edit2:由于您使用的是没有轻松constexpr功能的Visual Studio 2015,因此这是符合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...");
}
Run Code Online (Sandbox Code Playgroud)