以下是我读到的内容:using alias for static member functions?
在答案中,我看到了使用constexpr
的建议。将constexpr
用于void
函数的原因是什么。
请演示一个简单的用例。我是constexpr
的新手,所以在复杂的例子中我不理解要点。
答案 0 :(得分:5)
Rahul的回答引用了允许void
constexpr
函数的标准段落,但它没有给出用例。我想到的一个用例是拥有一个constexpr
类,并且通常会将辅助方法中的方法常见的因素排除在外。该标准明确提到了进行检查的功能,例如:断言。我手边没有具体的例子,但我可以想象像
class A
{
public:
constexpr X doSomething(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
constexpr X doSomethingElse(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
private:
constexpr void constraintOnYArguments(Y arg) {
}
constexpr void checkInvariant() {
// some checks
if (!some condition) {
throw std::logic_error("Oh no!");
}
}
};
答案 1 :(得分:2)
根据C ++ 14标准,void是文字类型
类型是文字类型,如果它是:
- 无效;或
- 标量类型;或
- 参考类型;或
- 一个文字类型的数组;或
- 具有以下所有属性的类类型(第9条): - 它有一个简单的析构函数,
- 它是聚合类型(8.5.1)或至少有一个constexpr 不是复制或移动的构造函数或构造函数模板 构造函数和
- 所有非静态数据成员和基类都是 非易失性文字类型。
来自here:
允许使用任意表达式语句 调用执行检查的函数并允许类似断言 结构体。 void也成为文字类型,因此constexpr 仅存在执行此类检查的函数可能会返回void。
答案 2 :(得分:1)
合理的用例是对 volatile 变量的操作。以下是使用GNU工具(g ++,ld)进行嵌入式编程的非常简化案例:
要将外围设备的地址设置为constexpr
,您需要将其放置在固定位置。这必须在链接描述文件中完成:
⋮
/* Define output sections */
SECTIONS
{
GPIO 0x48000000 (NOLOAD) : { *(.GPIO) }
⋮
现在,.GPIO
部分位于固定地址0x48000400
。外围设备可以通过包含易失性成员的POD建模。在以下示例中,POD名为gpio_t
,并且只有一个成员:mode
。可以在constexpr
函数中设置成员。当然,使用函数将变量设置为恒定值没有任何好处。但是在实际使用情况下,必须计算值和地址。例如,考虑为波特率设置一个分频器。
struct gpio_t {
volatile std::uint32_t mode;
};
__attribute__ ((section (".GPIO"))) gpio_t Gpio = {0};
static constexpr gpio_t *port {&Gpio};
static constexpr void init () {
port->mode = 42u;
};
void main {
init ();
⋮
};
注意:将整数强制转换为地址的C样式惯用法不起作用,因为它reinterpret_cast<>
不符合创建constexpr
指针的条件(请参见Since C++14 illegal)。以下失败:
constexpr gpio_t *port {(gpio_t *) 0x48000400};
答案 3 :(得分:0)
只要参数号是一个整数常量,这个constexpr版本将在编译时计算结果(仅限C ++ 11编译器)。当数字是运行时整数时,同样的函数完全能够在运行时计算结果。因此,您不需要同一程序的两个不同版本:一个用于编译时,另一个用于运行时。一个实现就是全部。