我不会使用正式的标准措辞,而是解释问题。
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
在通常放置 mutable 的地方放入一个 lambda(我不记得这个副手,所以我没有在上面的示例代码中包含 lambda)。
最后,我建议static
对 C++ 文件的本地函数使用匿名命名空间,并且在标头中都不使用。
这可能无法满足您的所有需求;的优点if constexpr
是您可以根据分支执行类型无效的事情。而且 C++ 不允许你根据函数参数的值做类型无效的事情。如果是这样,编译器无法在没有提供参数值的情况下编译函数体。
为了解决这个问题,您可以执行创建编译时字符串之类的操作。
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 中,您可以制作“更强”的编译时字符串,其中字符串实际上存在于 auto 参数中。但我不确定。