Visual C++ 因忽略 constexpr 函数限定符而臭名昭著,除非绝对需要。看下面的函数:
constexpr int multiply(int l, int r) noexcept
{
return l * r;
}
Run Code Online (Sandbox Code Playgroud)
根据标准,完全允许 Visual C++ 在编译时不计算右值:
auto three_times_four = multiply(3, 4);
Run Code Online (Sandbox Code Playgroud)
我一直在使用的解决方法是这种丑陋的力量:
constexpr auto constexpr_three_times_four = ;
auto not_constexpr_three_times_four = constexpr_three_times_four;
// use not_constexpr_three_times_four in non-constexpr contexts
// alternatively:
template<auto val>
inline constexpr auto ensure_constexpr = val;
auto not_constexpr_three_times_four = ensure_constexpr<multiply(3, 4)>;
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以提示编译器应该在编译时评估这些东西?
我对以下情况特别恼火:
namespace l
{
constexpr ::std::uint32_t operator""_crc32(const char * p, ::std::size_t const size) noexcept
{
return crc32(p);
}
}
//...
using namespace l;
search("foo"_crc32);//You don't want to evaluate this at runtime? too bad.
Run Code Online (Sandbox Code Playgroud)
那么,在这种情况下我该怎么做才能提示编译器并避免这些丑陋的修复?
没有机制可以“提示”编译器(任何编译器)constexpr在编译时“应该”调用函数。这不是什么constexpr是对。它不是加速代码执行的工具。它允许你这样做计算的工具都在编译时间内完成。
C++20 允许指定函数consteval,这确保函数必须在常量表达式中执行。但即使是该功能也不是为了性能。它在那里,以便他们可以添加语言的新特性(如反射值),这些特性只能在编译时存在,不能泄漏到运行时代码中。
C++20constinit允许您声明非常量表达式变量,其初始值设定项必须为常量表达式。这是最接近constexpr-as-a-performance-feature 的C++ 。
但除此之外,如果编译器的更高优化级别没有在编译时调用这些函数,那么编译器就会选择实现该功能的方式。