constexpr,还是不是 constexpr,这是个问题
constexpr, or not constexpr, that is the question
我在 C++ 中使用 constexpr
并注意到一个我想了解的奇怪行为。考虑标准 5.19 节中的这段代码。
constexpr int f1(int k) {
constexpr int x = k; // error: x is not initialized by a
// constant expression because lifetime of k
// began outside the initializer of x
return x;
}
作为错误状态,k
的生命周期开始于 x
的初始值设定项之外,因此我们不能确定 x
将是 常量表达式。
这里是相同功能的另一个版本。
constexpr int f1(int k) {
return k;
}
这个非常好用。所以问题是,为什么 k
的生命周期开始于 return 值的初始值设定项之外,或者不是,或者这是因为 RVO,从技术上讲,如果只是遵循标准,这也应该是一个错误?
还有另一个问题,这个问题实际上就是从这个问题中产生的。我试图写 constexpr
IPv4 class。为此,我使用了带 std::string_view
的构造函数。所以我能够在编译时使用 gcc 10.3 和 -std=c++20
constexpr IPv4 myIP{"192.168.0.0"};
constexpr size_t count = myIP.countOfDots(); // calls std::count which is constexpr in C++20
现在我想验证 IP 是否正确,所以我需要检查点数是否等于 3,我可以在此处轻松完成
if constexpr (count != 3)
问题是如何将其组织成某个函数,这也将允许我在编译时为任何给定的 IP 进行这样的检查,基本上我想要这样的东西
constexpr bool validateIP(const IPv4& ip);
如上例所示,我不能只在那个函数中使用 this
constexpr size_t count = ip.countOfDots();
那么可以按照我想要的方式去做吗?
constexpr
的函数意味着 可能 可以在编译时计算函数。但是,该函数还必须可以使用 运行 时间值调用,并产生 运行 时间结果。
constexpr
的变量必须是编译时常量。期间.
这对您的 validateIP
函数意味着您不需要创建 count
constexpr
。您可以编写一个函数并将其标记为 constexpr
.
当您使用编译时常量调用函数时,它将在编译时进行计算。
如果您使用 运行 时间值调用它,它将在 运行 时间进行评估。
#include <string_view>
#include <iostream>
constexpr bool validateIP(const std::string_view& ip) {
int count = 0;
for (auto& c : ip) {
if (c == '.') {
++count;
}
}
return count == 3;
}
int main()
{
// Assigning the value to a constexpr is not needed to make the function
// be evaluated at compile time, but it proves that it is in this case
constexpr auto isValid1 = validateIP("123.456.789.0");
std::cout << isValid1;
}
我在 C++ 中使用 constexpr
并注意到一个我想了解的奇怪行为。考虑标准 5.19 节中的这段代码。
constexpr int f1(int k) {
constexpr int x = k; // error: x is not initialized by a
// constant expression because lifetime of k
// began outside the initializer of x
return x;
}
作为错误状态,k
的生命周期开始于 x
的初始值设定项之外,因此我们不能确定 x
将是 常量表达式。
这里是相同功能的另一个版本。
constexpr int f1(int k) {
return k;
}
这个非常好用。所以问题是,为什么 k
的生命周期开始于 return 值的初始值设定项之外,或者不是,或者这是因为 RVO,从技术上讲,如果只是遵循标准,这也应该是一个错误?
还有另一个问题,这个问题实际上就是从这个问题中产生的。我试图写 constexpr
IPv4 class。为此,我使用了带 std::string_view
的构造函数。所以我能够在编译时使用 gcc 10.3 和 -std=c++20
constexpr IPv4 myIP{"192.168.0.0"};
constexpr size_t count = myIP.countOfDots(); // calls std::count which is constexpr in C++20
现在我想验证 IP 是否正确,所以我需要检查点数是否等于 3,我可以在此处轻松完成
if constexpr (count != 3)
问题是如何将其组织成某个函数,这也将允许我在编译时为任何给定的 IP 进行这样的检查,基本上我想要这样的东西
constexpr bool validateIP(const IPv4& ip);
如上例所示,我不能只在那个函数中使用 this
constexpr size_t count = ip.countOfDots();
那么可以按照我想要的方式去做吗?
constexpr
的函数意味着 可能 可以在编译时计算函数。但是,该函数还必须可以使用 运行 时间值调用,并产生 运行 时间结果。
constexpr
的变量必须是编译时常量。期间.
这对您的 validateIP
函数意味着您不需要创建 count
constexpr
。您可以编写一个函数并将其标记为 constexpr
.
当您使用编译时常量调用函数时,它将在编译时进行计算。
如果您使用 运行 时间值调用它,它将在 运行 时间进行评估。
#include <string_view>
#include <iostream>
constexpr bool validateIP(const std::string_view& ip) {
int count = 0;
for (auto& c : ip) {
if (c == '.') {
++count;
}
}
return count == 3;
}
int main()
{
// Assigning the value to a constexpr is not needed to make the function
// be evaluated at compile time, but it proves that it is in this case
constexpr auto isValid1 = validateIP("123.456.789.0");
std::cout << isValid1;
}