Любые творческие способы проверки, если строка содержит запрещенный символ во время компиляции или, по крайней мере, до ее использования?
Мне нужен способ проверить, что константная строка не содержит определенный символ во время компиляции. Я думал об использовании static_assert, но столкнулся с кирпичной стеной, потому что пытался использовать метод.find, который не является постоянным.
У меня есть возможность сделать проверку в конструкторе класса (экземпляры static const
члены указанного класса).
Но прежде чем кусать пулю (поскольку изменение поведения конструктора имеет и другие последствия), я хотел бы посмотреть, есть ли у кого-нибудь еще одна из этих креативных нестандартных идей, чтобы все еще сделать это, предпочтительно во время компиляции.
1 ответ
Под постоянной строкой, возможно, вы подразумеваете строковый литерал, для 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
если вы предполагаете, что получите только строковые литералы, а не произвольные массивы символов. Таким образом, вы не будете каждый раз проверять нулевой символ '\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...");
}