将代码转换为 constexpr
Convert code to constexpr
将代码转换为 constexpr
的一般提示是什么?比如说,有一种算法可以对(输入)几何图形进行一些几何变换。输入和输出的性质和大小各不相同,并且彼此之间存在非平凡的依赖关系。目前它实现为 class,目前使用 std::map
和 std::vector
(不失一般性)。
重构使用动态内存的代码以获得符合常量表达式要求的代码的方法是什么?
我可以想象 constexpr
兼容的容器和 constexpr
兼容的 "stack allocator" 实现的某种组合(用于足够大的存储),用于每个 value_type
容器.但是有一个问题:我从来没有遇到过这样的容器。但也许还有其他方法?
对于标准库中的大多数算法和实用程序 类(std::bitset
、std::array
等),您只需添加 constexpr
说明符无处不在 并尝试将结果存储在 constexpr
变量中。 很有可能,这将编译并 运行 成功 。另见 this Q&A.
通常会阻止此类代码编译的是 compile-time 常量表达式的当前语言限制之一,例如(查看 5.20 常量表达式 [expr.const] 完整列表)
- 动态内存分配(例如
std::inplace_merge
内)
- 虚函数(在
<iostream>
中)
- lambda 表达式(在 N4487 中提出并接受标准化)
reinterpret_cast
goto
(在 N4472 中提出但被拒绝标准化)
对于每个限制,都有办法绕过它
- 替代系统支持的动态内存分配
通过
new
/delete
就是自己写一个大内存池
全局 constexpr
数组。
- 虚函数的替代方法是存储一个函数数组
指针(调用
constexpr
函数)并通过
switch
语句。
- lambda 的替代方法是编写您自己的函数对象
constexpr operator()
.
-
reinterpret_cast
的替代方法是使用 constexpr
variant(下面有一个 union
)。
goto
的替代方法是编写更结构化的代码,使用
常规循环和分支。
在所有情况下,您将失去能够调用 new
/delete
或隐式动态调度的语法细节。您将不得不手动 allocate/deallocate 您的内存并手动 select 您的函数指针。
请注意,即使使用当前的 C++14/17 语言也可以 constexpr
制作标准库的大部分内容,但目前还不能。此外,标准库实现者被禁止添加额外的constexpr
功能(与被允许提供更强大的noexcept
支持相反)。
如果您认为应该有更多或更容易的 constexpr
支持(在语言和标准库中),请向您的供应商或 C++ 委员会投诉。
将代码转换为 constexpr
的一般提示是什么?比如说,有一种算法可以对(输入)几何图形进行一些几何变换。输入和输出的性质和大小各不相同,并且彼此之间存在非平凡的依赖关系。目前它实现为 class,目前使用 std::map
和 std::vector
(不失一般性)。
重构使用动态内存的代码以获得符合常量表达式要求的代码的方法是什么?
我可以想象 constexpr
兼容的容器和 constexpr
兼容的 "stack allocator" 实现的某种组合(用于足够大的存储),用于每个 value_type
容器.但是有一个问题:我从来没有遇到过这样的容器。但也许还有其他方法?
对于标准库中的大多数算法和实用程序 类(std::bitset
、std::array
等),您只需添加 constexpr
说明符无处不在 并尝试将结果存储在 constexpr
变量中。 很有可能,这将编译并 运行 成功 。另见 this Q&A.
通常会阻止此类代码编译的是 compile-time 常量表达式的当前语言限制之一,例如(查看 5.20 常量表达式 [expr.const] 完整列表)
- 动态内存分配(例如
std::inplace_merge
内) - 虚函数(在
<iostream>
中) - lambda 表达式(在 N4487 中提出并接受标准化)
reinterpret_cast
goto
(在 N4472 中提出但被拒绝标准化)
对于每个限制,都有办法绕过它
- 替代系统支持的动态内存分配
通过
new
/delete
就是自己写一个大内存池 全局constexpr
数组。 - 虚函数的替代方法是存储一个函数数组
指针(调用
constexpr
函数)并通过switch
语句。 - lambda 的替代方法是编写您自己的函数对象
constexpr operator()
. -
reinterpret_cast
的替代方法是使用constexpr
variant(下面有一个union
)。 goto
的替代方法是编写更结构化的代码,使用 常规循环和分支。
在所有情况下,您将失去能够调用 new
/delete
或隐式动态调度的语法细节。您将不得不手动 allocate/deallocate 您的内存并手动 select 您的函数指针。
请注意,即使使用当前的 C++14/17 语言也可以 constexpr
制作标准库的大部分内容,但目前还不能。此外,标准库实现者被禁止添加额外的constexpr
功能(与被允许提供更强大的noexcept
支持相反)。
如果您认为应该有更多或更容易的 constexpr
支持(在语言和标准库中),请向您的供应商或 C++ 委员会投诉。