`编译时参数未知时,不调用constexpr`构造函数 目前我正在阅读Scott Meyers的有效的现代C++(项目15——尽可能使用CONTXPR)。作者说:

`编译时参数未知时,不调用constexpr`构造函数 目前我正在阅读Scott Meyers的有效的现代C++(项目15——尽可能使用CONTXPR)。作者说:,c++,c++11,c++14,C++,C++11,C++14,当使用一个或多个 编译过程中不知道,它的作用类似于普通函数, 在运行时计算其结果。这意味着你不需要两个 函数来执行相同的操作,一个用于编译时 常数,一个用于所有其他值。constexpr函数可以实现这一点 全部 我在中尝试了以下代码段 Coliru使用gcc编译器。 所以,我不明白问题出在哪里。也许我错过了什么…(我的): constepr变量必须满足以下要求: 其类型必须是LiteralType 它必须立即初始化 其初始化的完整表达式,包括所有隐式转换、构造函数调用等,必须是常量表达式 在

当使用一个或多个 编译过程中不知道,它的作用类似于普通函数, 在运行时计算其结果。这意味着你不需要两个 函数来执行相同的操作,一个用于编译时 常数,一个用于所有其他值。constexpr函数可以实现这一点 全部

我在中尝试了以下代码段

Coliru
使用gcc编译器。 所以,我不明白问题出在哪里。也许我错过了什么…

(我的):

constepr
变量必须满足以下要求:

  • 其类型必须是
    LiteralType
  • 它必须立即初始化
  • 其初始化的完整表达式,包括所有隐式转换、构造函数调用等,必须是常量表达式
在你的例子中

constexpr Point p2(a, b);
a
b
不是常量表达式。为了使它们成为常量表达式,需要将
get_a
get_b
a
b
标记为
constepr

constexpr double get_a() noexcept
{
    return 5.5;
}

constexpr double get_b() noexcept
{
    return 5.6;
}
Point p2(a, b); // This works, even though Point(int,int) is constexpr

来自(我的):

constepr
变量必须满足以下要求:

  • 其类型必须是
    LiteralType
  • 它必须立即初始化
  • 其初始化的完整表达式,包括所有隐式转换、构造函数调用等,必须是常量表达式
在你的例子中

constexpr Point p2(a, b);
a
b
不是常量表达式。为了使它们成为常量表达式,需要将
get_a
get_b
a
b
标记为
constepr

constexpr double get_a() noexcept
{
    return 5.5;
}

constexpr double get_b() noexcept
{
    return 5.6;
}
Point p2(a, b); // This works, even though Point(int,int) is constexpr


您误解了Scott的解释:他并不是说您可以使用非常量数据创建
constexpr
对象。这样的构造不应该起作用

constexpr Point p2(a, b);
因为编译器不知道
a
b
的值,所以不能向编译器声明
p2
对象是
constepr

他的意思是当你定义一个
constexpr
函数或成员函数时,就像这样

int constexpr foo(int a, int b) {
    return 2*a + b;
}
a
b
是编译时常量时,它显然会工作,但即使
a
b
是变量,它也会继续工作:

cout << foo(2, 5) << endl; // This obviously works
int a, b;
cin >> a >> b;
cout << foo(a, b) << endl; // This works too

您误解了Scott的解释:他并不是说您可以使用非常量数据创建
constexpr
对象。这样的构造不应该起作用

constexpr Point p2(a, b);
因为编译器不知道
a
b
的值,所以不能向编译器声明
p2
对象是
constepr

他的意思是当你定义一个
constexpr
函数或成员函数时,就像这样

int constexpr foo(int a, int b) {
    return 2*a + b;
}
a
b
是编译时常量时,它显然会工作,但即使
a
b
是变量,它也会继续工作:

cout << foo(2, 5) << endl; // This obviously works
int a, b;
cin >> a >> b;
cout << foo(a, b) << endl; // This works too

您不应该将
p2
声明为
constexpr
,因为它不能是。所以只需
点p2(a,b)没问题。为什么?在
p1
中,case成员在编译时初始化,因为我们有编译时已知的参数:2.3、4.4。在
p2
情况下,我们不知道
a
b
编译时的值,这并不意味着成员应该在运行时初始化?(当使用编译期间未知的一个或多个值调用constexpr函数时,它的行为与普通函数类似,在运行时计算其结果。)您的引用仅引用函数。如果你声明一个对象或表达式
constexpr
,你需要在编译时对它求值,而
p2
不能像宋元耀指出的那样。@DavidHovsepyan是的,它是在运行时求值的,所以它不能是
constexpr
,这需要在编译时求值。好的,我知道了。我只是认为编译器会理解构造函数将在运行时被调用,并且在声明
p2
之前它将忽略
constexpr
关键字。您不应该将
p2
声明为
constexpr
,因为它不能被调用。所以只需
点p2(a,b)没问题。为什么?在
p1
中,case成员在编译时初始化,因为我们有编译时已知的参数:2.3、4.4。在
p2
情况下,我们不知道
a
b
编译时的值,这并不意味着成员应该在运行时初始化?(当使用编译期间未知的一个或多个值调用constexpr函数时,它的行为与普通函数类似,在运行时计算其结果。)您的引用仅引用函数。如果你声明一个对象或表达式
constexpr
,你需要在编译时对它求值,而
p2
不能像宋元耀指出的那样。@DavidHovsepyan是的,它是在运行时求值的,所以它不能是
constexpr
,这需要在编译时求值。好的,我知道了。我只是认为编译器会理解构造函数将在运行时被调用,并且在声明
p2
之前它会忽略
constexpr
关键字。在我的例子中
a
b
不是变量?实际上问题是我声明
p2
constepr
@DavidHovsepyan绝对是的。这意味着您可以将它们传递给
constexpr
函数,但这并不意味着函数结果将是
constexpr