如何在 constexpr 上下文中使用 if-constexpt 比较 string_view
How to compare string_view using if-constexpt in a constexpr context
是否可以在 constexpr 上下文中使用“if constexpr”来比较 std::string_view?以及为什么 is_hello_2 和 is_hello_4 编译失败显示错误:“'s' 不是常量表达式”
static constexpr bool is_hello_1(auto s) {
return s == "hello";
}
static constexpr bool is_hello_2(auto s) {
if constexpr (s == "hello") {
return true;
}
return false;
}
static constexpr auto is_hello_3 = [](auto s) {
return s == "hello";
};
static constexpr auto is_hello_4 = [](auto s) {
if constexpr (s == "hello") {
return true;
}
return false;
};
考虑主要功能(https://godbolt.org/z/zEcnb8):
int main(int argc, char **argv) {
static constexpr const std::string_view s1 ("hello");
if constexpr (s1 == "hello"){}
if constexpr (is_hello_1(s1)){}
// if constexpr (is_hello_2(s1)){} // <- doesn't compile
if constexpr (is_hello_3(s1)){}
// if constexpr (is_hello_4(s1)){} // <- doesn't compile
return 0;
}
有没有办法修复“is_hello_2”和“is_hello_4”?
Is there a way to fix "is_hello_2" and "is_hello_4"?
从 is_hello_2
或 is_hello_4
中的 if
中删除 constexpr
。
How to compare string_view using if-constexpt in a constexpr context
通常,和其他地方一样。
static constexpr bool is_hello_5() {
constexpr const std::string_view s1 ("hello");
if constexpr (s1 == "hello") {
return true;
}
return false;
}
函数参数值不是常量表达式,您不能在 if constexpr
.
中使用它们
从函数的角度思考(好像你在函数作用域内):如果函数参数未知,它如何在编译时解析你的代码?这与您在 main 函数中将 s1
标记为 constexpr
的原因相同。如果你不这样做 - 代码将无法编译。
所以你要做的就是从 is_hello2
和 is_hello4
中删除 constexpr
。这不会阻止函数在 constexpr 中使用。
#include <string_view>
static constexpr bool is_hello_1(auto s) {
return s == "hello";
}
static constexpr bool is_hello_2(auto s) {
if (s == "hello") {
return true;
}
return false;
}
static constexpr auto is_hello_3 = [](auto s) {
return s == "hello";
};
static constexpr auto is_hello_4 = [](auto s) {
if (s == "hello") {
return true;
}
return false;
};
int main(int argc, char **argv) {
static constexpr std::string_view s1 ("hello");
static_assert(s1 == "hello");
static_assert(is_hello_1(s1));
static_assert(is_hello_2("hello"));
static_assert(is_hello_3(s1));
static_assert(is_hello_4(s1));
return 0;
}
但是在类型和 none-type 模板参数上使用 if constexpr 是完全没问题的:
template<int s>
static constexpr auto is_5 = []() {
if constexpr (s == 5) {
return true;
}
return false;
};
static_assert(is_5<5>());
很遗憾,您现在不能将 std::string_view 作为 non-type 模板参数。
我不会使用正式的标准措辞,而是说明问题。
if constexpr
要求它的所有参数总是 constexpr
.
constexpr
函数的参数有时是 constexpr
。
您可以使用非 constexpr
个参数调用 constexpr
个函数。
尝试consteval
。
#include <string_view>
using namespace std::literals;
consteval bool is_hello_1(auto s) {
return s == "hello";
}
consteval bool is_hello_2(auto s) {
if (s == "hello") {
return true;
}
return false;
}
int main(int argc, char **argv) {
static constexpr std::string_view s1 ("hello");
static_assert(s1 == "hello");
static_assert(is_hello_1(s1));
static_assert(is_hello_2("hello"sv));
return 0;
}
您可以将 consteval
放在通常放置可变的 lambda 中(我不记得这个 off-hand,所以我没有在上面的示例代码中包含 lambda)。
最后,我建议对 static
C++ 文件的局部函数使用匿名名称空间,并且在 headers.
中都不使用
这可能无法满足您的所有需求; if constexpr
的优点是你可以根据分支做 type-invalid 事情。 C++ 不允许您根据函数参数的值做 type-invalid 事情;如果是这样,编译器将无法在不提供参数值的情况下编译函数的 body。
要解决这个问题,您可以创建一个 compile-time 字符串。
template<auto s>
consteval bool is_hello_2() {
if constexpr (s == "hello") {
return true;
}
return false;
}
并用
调用它
template<std::size_t N>
struct compile_time_string : std::array<char, N+1> {
constexpr std::array<char, N+1>& buffer() { return *this; }
constexpr std::array<char, N+1> const& buffer() const { return *this; }
constexpr std::string_view view() const { return {this->data(), this->data()+this->size()}; }
private:
template<std::size_t...Is>
constexpr compile_time_string( char const* str, std::index_sequence<Is...> ):
std::array<char, N+1>{{ str[Is]..., char(0) }}
{}
public:
explicit constexpr compile_time_string( char const* str ):
compile_time_string( str, std::make_index_sequence<N>{} )
{}
explicit constexpr compile_time_string( std::array<char, N+1> buff ) :
std::array<char, N+1>(buff)
{}
constexpr compile_time_string( compile_time_string const& ) = default;
compile_time_string() = delete;
constexpr auto operator<=>( compile_time_string const& o ) const = default;
constexpr bool operator==( compile_time_string const& o ) const = default;
template<std::size_t N_arg>
friend constexpr auto operator==( char const(&lhs)[N_arg], compile_time_string const& rhs )
{
return std::string_view{ lhs, lhs+N_arg } == rhs.view();
}
template<std::size_t N_arg>
friend constexpr auto operator==( compile_time_string const& lhs, char const(&rhs)[N_arg] )
{
return lhs.view() == std::string_view{ rhs, rhs+N_arg };
}
};
template<std::size_t N>
compile_time_string( char const(&)[N] )->compile_time_string<N-1>;
template<auto s>
consteval bool is_hello_3() {
if (s == "hello") {
return true;
}
return false;
}
static_assert(is_hello_3<compile_time_string("hello")>());
我削减了编译时间字符串。对于更多类型,您需要更好的 <=> 和 == 等。
此外,我认为在 C++20 中,您可以创建“更强”的编译时字符串,其中该字符串实际上存在于自动参数中。但我不确定。
是否可以在 constexpr 上下文中使用“if constexpr”来比较 std::string_view?以及为什么 is_hello_2 和 is_hello_4 编译失败显示错误:“'s' 不是常量表达式”
static constexpr bool is_hello_1(auto s) {
return s == "hello";
}
static constexpr bool is_hello_2(auto s) {
if constexpr (s == "hello") {
return true;
}
return false;
}
static constexpr auto is_hello_3 = [](auto s) {
return s == "hello";
};
static constexpr auto is_hello_4 = [](auto s) {
if constexpr (s == "hello") {
return true;
}
return false;
};
考虑主要功能(https://godbolt.org/z/zEcnb8):
int main(int argc, char **argv) {
static constexpr const std::string_view s1 ("hello");
if constexpr (s1 == "hello"){}
if constexpr (is_hello_1(s1)){}
// if constexpr (is_hello_2(s1)){} // <- doesn't compile
if constexpr (is_hello_3(s1)){}
// if constexpr (is_hello_4(s1)){} // <- doesn't compile
return 0;
}
有没有办法修复“is_hello_2”和“is_hello_4”?
Is there a way to fix "is_hello_2" and "is_hello_4"?
从 is_hello_2
或 is_hello_4
中的 if
中删除 constexpr
。
How to compare string_view using if-constexpt in a constexpr context
通常,和其他地方一样。
static constexpr bool is_hello_5() {
constexpr const std::string_view s1 ("hello");
if constexpr (s1 == "hello") {
return true;
}
return false;
}
函数参数值不是常量表达式,您不能在 if constexpr
.
从函数的角度思考(好像你在函数作用域内):如果函数参数未知,它如何在编译时解析你的代码?这与您在 main 函数中将 s1
标记为 constexpr
的原因相同。如果你不这样做 - 代码将无法编译。
所以你要做的就是从 is_hello2
和 is_hello4
中删除 constexpr
。这不会阻止函数在 constexpr 中使用。
#include <string_view>
static constexpr bool is_hello_1(auto s) {
return s == "hello";
}
static constexpr bool is_hello_2(auto s) {
if (s == "hello") {
return true;
}
return false;
}
static constexpr auto is_hello_3 = [](auto s) {
return s == "hello";
};
static constexpr auto is_hello_4 = [](auto s) {
if (s == "hello") {
return true;
}
return false;
};
int main(int argc, char **argv) {
static constexpr std::string_view s1 ("hello");
static_assert(s1 == "hello");
static_assert(is_hello_1(s1));
static_assert(is_hello_2("hello"));
static_assert(is_hello_3(s1));
static_assert(is_hello_4(s1));
return 0;
}
但是在类型和 none-type 模板参数上使用 if constexpr 是完全没问题的:
template<int s>
static constexpr auto is_5 = []() {
if constexpr (s == 5) {
return true;
}
return false;
};
static_assert(is_5<5>());
很遗憾,您现在不能将 std::string_view 作为 non-type 模板参数。
我不会使用正式的标准措辞,而是说明问题。
if constexpr
要求它的所有参数总是 constexpr
.
constexpr
函数的参数有时是 constexpr
。
您可以使用非 constexpr
个参数调用 constexpr
个函数。
尝试consteval
。
#include <string_view>
using namespace std::literals;
consteval bool is_hello_1(auto s) {
return s == "hello";
}
consteval bool is_hello_2(auto s) {
if (s == "hello") {
return true;
}
return false;
}
int main(int argc, char **argv) {
static constexpr std::string_view s1 ("hello");
static_assert(s1 == "hello");
static_assert(is_hello_1(s1));
static_assert(is_hello_2("hello"sv));
return 0;
}
您可以将 consteval
放在通常放置可变的 lambda 中(我不记得这个 off-hand,所以我没有在上面的示例代码中包含 lambda)。
最后,我建议对 static
C++ 文件的局部函数使用匿名名称空间,并且在 headers.
这可能无法满足您的所有需求; if constexpr
的优点是你可以根据分支做 type-invalid 事情。 C++ 不允许您根据函数参数的值做 type-invalid 事情;如果是这样,编译器将无法在不提供参数值的情况下编译函数的 body。
要解决这个问题,您可以创建一个 compile-time 字符串。
template<auto s>
consteval bool is_hello_2() {
if constexpr (s == "hello") {
return true;
}
return false;
}
并用
调用它template<std::size_t N>
struct compile_time_string : std::array<char, N+1> {
constexpr std::array<char, N+1>& buffer() { return *this; }
constexpr std::array<char, N+1> const& buffer() const { return *this; }
constexpr std::string_view view() const { return {this->data(), this->data()+this->size()}; }
private:
template<std::size_t...Is>
constexpr compile_time_string( char const* str, std::index_sequence<Is...> ):
std::array<char, N+1>{{ str[Is]..., char(0) }}
{}
public:
explicit constexpr compile_time_string( char const* str ):
compile_time_string( str, std::make_index_sequence<N>{} )
{}
explicit constexpr compile_time_string( std::array<char, N+1> buff ) :
std::array<char, N+1>(buff)
{}
constexpr compile_time_string( compile_time_string const& ) = default;
compile_time_string() = delete;
constexpr auto operator<=>( compile_time_string const& o ) const = default;
constexpr bool operator==( compile_time_string const& o ) const = default;
template<std::size_t N_arg>
friend constexpr auto operator==( char const(&lhs)[N_arg], compile_time_string const& rhs )
{
return std::string_view{ lhs, lhs+N_arg } == rhs.view();
}
template<std::size_t N_arg>
friend constexpr auto operator==( compile_time_string const& lhs, char const(&rhs)[N_arg] )
{
return lhs.view() == std::string_view{ rhs, rhs+N_arg };
}
};
template<std::size_t N>
compile_time_string( char const(&)[N] )->compile_time_string<N-1>;
template<auto s>
consteval bool is_hello_3() {
if (s == "hello") {
return true;
}
return false;
}
static_assert(is_hello_3<compile_time_string("hello")>());
我削减了编译时间字符串。对于更多类型,您需要更好的 <=> 和 == 等。
此外,我认为在 C++20 中,您可以创建“更强”的编译时字符串,其中该字符串实际上存在于自动参数中。但我不确定。