constexpr 相关问题

constexpr是C ++ 11中引入的修饰符,它通知编译器函数或变量的值是已知的,或者可以在编译时计算。因此,它可以在不可能的地方用作常数。

在 msvc 的 constexpr 上下文中未调用构造函数体

我试图将初始值设定项列表传递给结构的构造函数,其参数是 std::vector,但我在 Visual Studio 社区中得到了意外的结果。这是重现的代码...

回答 1 投票 0

可以在常量表达式中使用特定于类的释放函数吗?

我可以定义一个特定于类的释放函数并在常量表达式中使用它吗? 例如破坏性删除: #包括 结构体A { constexpr void 运算符删除(A...

回答 1 投票 0

内联与 constexpr?

使用新的 C++11 标准,什么时候应该使用 inline 关键字而不是 constexpr 关键字? constexpr 关键字是否提供了比内联任何额外的优化,或者它只是断言

回答 3 投票 0

为什么 clang 允许在 constexpr 中进行这种 C 风格的转换?

以下代码可以使用 clang++ 14 进行编译,但不能使用 g++ 12 进行编译(这会失败,因为 constexpr 中不允许 reinterpret_cast)。 constexpr int* 转换(char* a) { 返回(int*)(a); } int 我...

回答 1 投票 0

使用 constexpr if 定义并声明 const std::array

我正在尝试实现高斯-勒让德求积,我想要一个模板化函数 将点数作为模板参数。 现在我有这个: 模板 我正在尝试实现高斯-勒让德求积,并且我想要一个模板化函数 将点数作为模板参数。 现在我有这个: template<int number_of_quadrature_points> double gaussian_quadrature_integral_core(double (*f)(double), double from, double to){ double scaling_factor = (to-from)/2; double average_factor = (from+to)/2; std::array<double, number_of_quadrature_points> factors; std::array<double, number_of_quadrature_points> points; if constexpr(number_of_quadrature_points == 2){ factors = {1, 1}; points = {-1.0/sqrt(3), 1.0/sqrt(3)}; } if constexpr(number_of_quadrature_points == 3){ factors = {5.0/9.0, 8.0/9.0, 5.0/9.0}; points = {-sqrt(3.0/5.0), 0, sqrt(3.0/5.0)}; } double sum = 0; for(int i = 0; i < number_of_quadrature_points; i++){ sum += factors.at(i)*((*f)(scaling_factor*points.at(i)+average_factor)); } sum *= scaling_factor; return sum; } 如您所见,当模板参数发生变化时,不仅数组大小发生变化,而且内容也发生变化,但对于给定的大小,内容是众所周知的。出于这个原因,我认为如果 std::arrays 是 const static 会更好,因为该函数被调用很多次。 现在我只能使用 if constexpr 来声明数组,但是如何使用它来定义和声明数组,以便它在 if constexpr 范围之外可见并且数组只定义一次? 添加两个辅助函数就足够了(如果您使用的是 C++20): template<unsigned N> constexpr auto init_factors() { std::array<double, N> rv; if constexpr(N == 2){ rv = {1., 1.}; } else { rv = {5.0/9.0, 8.0/9.0, 5.0/9.0}; } return rv; } template<unsigned N> constexpr auto init_points() { std::array<double, N> rv; if constexpr(N == 2){ rv = {-1.0/std::sqrt(3.), 1.0/std::sqrt(3.)}; } else { rv = {-std::sqrt(3.0/5.0), 0, std::sqrt(3.0/5.0)}; } return rv; } template<unsigned number_of_quadrature_points> double gaussian_quadrature_integral_core(double (*f)(double), double from, double to) { static constexpr auto factors = init_factors<number_of_quadrature_points>(); static constexpr auto points = init_points<number_of_quadrature_points>(); [...] 为了防止使用错误的点数,您可以添加 static_assert template<unsigned number_of_quadrature_points> double gaussian_quadrature_integral_core(double (*f)(double), double from, double to) { static_assert(number_of_quadrature_points==2||number_of_quadrature_points==3); ...或者如果您想稍后进行专业化,请阻止使用 SFINAE 进行匹配: #include <type_traits> template<unsigned number_of_quadrature_points> std::enable_if_t<number_of_quadrature_points==2||number_of_quadrature_points==3, double> gaussian_quadrature_integral_core(double (*f)(double), double from, double to) { 您可能有模板变量: template <std::size_t N> static constexpr std::array<double, N> factors; template <std::size_t N> static constexpr std::array<double, N> points; template <> constexpr std::array<double, 2> factors<2>{{1, 1}}; template <> constexpr std::array<double, 2> points<2>{{-1.0 / sqrt(3), 1.0 / sqrt(3)}}; template <> constexpr std::array<double, 3> factors<3>{{5.0 / 9.0, 8.0 / 9.0, 5.0 / 9.0}}; template <> constexpr std::array<double, 3> points<3>{{-sqrt(3.0 / 5.0), 0, sqrt(3.0 / 5.0)}}; 然后 template<int number_of_quadrature_points> double gaussian_quadrature_integral_core(double (*f)(double), double from, double to) { const double scaling_factor = (to - from) / 2; const double average_factor = (from + to) / 2; double sum = 0; for(int i = 0; i < number_of_quadrature_points; i++){ sum += factors<number_of_quadrature_points>[i] * ((*f)(scaling_factor * points<number_of_quadrature_points>[i] + average_factor)); } sum *= scaling_factor; return sum; } 演示 请注意,如果您没有 constexpr constexpr(而 const 没有),则必须将 sqrt 替换为 std::。 您可以使用本主题中类似的内容: 有没有办法在 C++ 模板特化中对常量值参数设置条件? 因此,我们使用 std::enable_if 和 SFINAE 创建两个模板专业化。我们通过模板参数number_of_quadrature_points来区分它们。这样我们就有了全局参数,不必多次定义和实例化。此代码使用 c++17 编译。 我还建议使用现代方法 std::function<> 而不是函数指针。 #include <array> #include <cmath> #include <iostream> #include <functional> template<int number_of_quadrature_points, typename E=void> struct gaussian_quadrature_params { }; template<int number_of_quadrature_points> struct gaussian_quadrature_params<number_of_quadrature_points, std::enable_if_t<(number_of_quadrature_points==2)> > { constexpr static const std::array<double, number_of_quadrature_points> factors = {1, 1}; constexpr static const std::array<double, number_of_quadrature_points> points = {-1.0/sqrt(3), 1.0/sqrt(3)}; }; template<int number_of_quadrature_points> struct gaussian_quadrature_params<number_of_quadrature_points, std::enable_if_t<(number_of_quadrature_points==3)> > { constexpr static const std::array<double, number_of_quadrature_points> factors = {5.0/9.0, 8.0/9.0, 5.0/9.0}; constexpr static const std::array<double, number_of_quadrature_points> points = {-sqrt(3.0/5.0), 0, sqrt(3.0/5.0)}; }; double f(double x) { return x; } template<int number_of_quadrature_points> double gaussian_quadrature_integral_core(std::function<double(double)> f, double from, double to){ double scaling_factor = (to-from)/2; double average_factor = (from+to)/2; double sum = 0; for(int i = 0; i < number_of_quadrature_points; i++){ sum += gaussian_quadrature_params<number_of_quadrature_points>::factors.at(i)*(f(scaling_factor*gaussian_quadrature_params<number_of_quadrature_points>::points.at(i)+average_factor)); } sum *= scaling_factor; return sum; } int main() { std::cout << gaussian_quadrature_integral_core<2>(f, -1.0, 1.0) << std::endl; std::cout << gaussian_quadrature_integral_core<3>(f, -1.0, 1.0) << std::endl; } 怎么样 // N: number_of_quadrature_points template<int N> double gaussian_quadrature_integral_core(double (*f)(double), double from, double to) { constexpr std::array<double, N> factors = []() ->std::array<double, N>{ if constexpr(N == 2) return {1.0, 1.0}; else if constexpr(N == 3) return {5.0 / 9.0, 8.0 / 9.0, 5.0 / 9.0}; // ... other N cases }(); constexpr std::array<double, N> points= []()->auto{ if constexpr(N == 2) return std::array<double, N>{-1.0 / std::sqrt(3), 1.0 / std::sqrt(3)}; else if constexpr(N == 3) return std::array<double, N>{-std::sqrt(3.0 / 5.0), 0, std::sqrt(3.0 / 5.0)}; // ... other N cases }(); double scaling_factor = (to - from) / 2; double average_factor = (from + to) / 2; double sum = 0; for (int i = 0; i < N; i++) sum += factors.at(i)*((*f)(scaling_factor * points.at(i) + average_factor)); sum *= scaling_factor; return sum; } 使用 if constexpr 声明和定义数组。

回答 4 投票 0

引用求值什么时候会使某些东西不是常量表达式?

考虑以下代码片段: 结构测试1 { 静态 constexpr int get() { 返回1; } }; 结构测试2 { constexpr int get() const { 返回1; } }; 模板<...

回答 1 投票 0

你能在编译时将 std::vector 转换为 std::array 而不使向量两次吗?

我正在使用 std::vector 在编译时计算一些数据,并希望将结果作为数组返回,以便可以在运行时进一步使用。我在不做任何事情的情况下设置数组大小时遇到问题...

回答 1 投票 0

在编译时将 std::vector 转换为 std::array

我正在使用 std::vector 在编译时计算一些数据,并希望将结果作为数组返回,以便可以在运行时进一步使用。我在不做任何事情的情况下设置数组大小时遇到问题...

回答 1 投票 0

constexpr 用于通过引用传入的值

我有这段代码可以编译 #包括 结构体A{ std::bitset<50> b; }; 无效测试(A a){ static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in

回答 2 投票 0

引用求值什么时候会使某些东西不是常量表达式?

考虑以下代码片段: 结构测试1 { 静态 constexpr int get() { 返回1; } }; 结构测试2 { constexpr int get() const { 返回1; } }; 模板<...

回答 1 投票 0

在 constexpr 上下文中记录替代方案/解决方案

目前,我现有的代码中约有 90% 是 constexpr。 这就提出了一个问题,我如何向所述代码添加像样的日志记录功能。 目前,我有以下日志记录代码: #定义日志...

回答 1 投票 0

更多在堆栈上分配任意空间的非标准方法

目前,我正在使用 gcc,它允许在 C++ constexpr 函数中使用 C 可变长度数组(不要问我为什么)。当然,这不是标准行为,但会导致设计...

回答 1 投票 0

带参数化构造函数的 C++ 静态分配

我想使用编译时分配(静态分配)通过其参数化构造函数来分配类的对象。传递的参数是编译时常量,它...

回答 1 投票 0

lambda 函数/表达式支持 constexpr 吗?

结构测试 { 静态常量 int 值 = []() -> int { return 0; } (); }; 使用 gcc-4.6 我得到类似错误:函数需要为 constexpr 的信息。我尝试过多种推杆组合

回答 5 投票 0

如何让 MSVC 在 c++20 编译时查看静态 constexpr 成员变量和函数?

背景 我试图在编译时在 CRTP 类中访问 constexpr 变量。下面是一个 MVCE。 模板 结构体CRTP { 静态 constexpr int get_va...

回答 1 投票 0

条件定义变量(static if)

在多种情况下,我想使用类似的东西 模板 结构S { 整数值; if constexpr(条件) /*#if 条件*/ 双倍 my_extra_member_variable; /*#结束...

回答 1 投票 0

constexpr 用指针初始化

我正在尝试使用指向 int 的指针初始化 constexpr 声明,该指针是 const 对象。我还尝试使用非 const 类型的对象来定义对象。 代码: #包括 我正在尝试使用指向 int 的指针初始化 constexpr 声明,该指针是 const 对象。我还尝试使用非 const 类型的对象来定义对象。 代码: #include <iostream> int main() { constexpr int *np = nullptr; // np is a constant to int that points to null; int j = 0; constexpr int i = 42; // type of i is const int constexpr const int *p = &i; // p is a constant pointer to the const int i; constexpr int *p1 = &j; // p1 is a constant pointer to the int j; } g++ 日志: constexpr.cc:8:27: error: ‘& i’ is not a constant expression constexpr.cc:9:22: error: ‘& j’ is not a constant expression 我相信这是因为 main 中的对象没有固定地址,因此 g++ 向我抛出错误消息;我该如何纠正这个问题?不使用文字类型。 让他们static修复他们的地址: int main() { constexpr int *np = nullptr; // np is a constant to int that points to null; static int j = 0; static constexpr int i = 42; // type of i is const int constexpr const int *p = &i; // p is a constant pointer to the const int i; constexpr int *p1 = &j; // p1 is a constant pointer to the int j; } 这称为 地址常量表达式 [5.19p3]: 地址常量表达式是纯右值核心常量表达式 指针类型,计算结果为具有 static 的对象的地址 存储持续时间、函数地址或空指针 值,或 std::nullptr_t 类型的纯右值核心常量表达式。 #include <iostream> // define i/j outside the function body, as mentioned in the book "c++ primer" int j = 0; constexpr int i = 42; // type of i is const int int main() { constexpr int *np = nullptr; // np is a constant to int that points to null; constexpr const int *p = &i; // p is a constant pointer to the const int i; constexpr int *p1 = &j; // p1 is a constant pointer to the int j; }

回答 2 投票 0

C++ 在 constexpr 中合成链表

我有以下问题,考虑这样的链表: 结构元素{ 结构元素* const next; // 这里需要const constexpr Car(结构元素* _nxt) :下一个(_nxt) { } ...

回答 1 投票 0

如何在 constexpr 表达式中从 const void* 进行转换?

我正在尝试将 memchr 重新实现为 constexpr (1)。我没有预料到会出现问题,因为我已经用 strchr 成功地完成了同样的事情,这非常相似。 然而 clang 和 gcc 都拒绝......

回答 2 投票 0

C++14 我应该多久使用一次 constexpr?

我一直在读一本关于C++14/11的书。我刚刚读完关于 constexpr 关键字的一章。我知道它的用途,但我应该多久使用一次 constexpr?我应该在代码中使用它吗...

回答 2 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.