在编译时不知道参数时,不会调用`constexpr`构造函数

Dav*_*yan 1 c++ c++11 c++14

目前我正在阅读Scott Meyers的Effective Modern C++(第15项 - 尽可能使用constexpr).作者说:

当使用编译期间未知的一个或多个值调用constexpr函数时,它的作用类似于普通函数,在运行时计算其结果.这意味着您不需要两个函数来执行相同的操作,一个用于编译时常量,另一个用于所有其他值.constexpr功能可以完成所有工作.

我在http://coliru.stacked-crooked.com/中尝试了以下代码片段

#include <iostream>

class Point
{
    public:
        constexpr Point(double a, double b) noexcept
            : _a(a), _b(b)
        {
        }

        void print() const noexcept
        {
            std::cout << "a -> " << _a << "\tb -> " << _b << std::endl;
        }

    private:
        double _a;
        double _b;
};

double get_a() noexcept
{
    return 5.5;
}

double get_b() noexcept
{
    return 5.6;
}


int main()
{
    constexpr Point p1(2.3, 4.4);
    p1.print();
    int a = get_a();
    int b = get_b();
    constexpr Point p2(a, b);
    p2.print();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在创建p1对象的情况下,所有操作都按预期进行:参数是已知的编译时间,并且成员已正确初始化.在创建p2对象的情况下,虽然我们在编译时不知道ab变量的值,但它应该在我的理解中起作用,因为构造函数应该充当普通函数.但是我收到以下错误消息:

main.cpp: In function 'int main()'
main.cpp:38:28: error: the value of 'a' is not usable in a constant expression
     constexpr Point p2(a, b);
                            ^
main.cpp:36:9: note: 'int a' is not const
     int a = get_a();
         ^
main.cpp:38:28: error: the value of 'b' is not usable in a constant expression
     constexpr Point p2(a, b);
                            ^
main.cpp:37:9: note: 'int b' is not const
     int b = get_b();
Run Code Online (Sandbox Code Playgroud)

Coliru使用gcc编译器.所以,我不明白是什么问题.也许我错过了一些东西......

Vit*_*meo 6

cppreference (强调我的):

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

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

在你的例子中......

constexpr Point p2(a, b);
Run Code Online (Sandbox Code Playgroud)

...... ab不是常量表达式.为了使他们常量表达式,你需要标记get_a,get_b,a,和bconstexpr:

constexpr double get_a() noexcept
{
    return 5.5;
}

constexpr double get_b() noexcept
{
    return 5.6;
}
Run Code Online (Sandbox Code Playgroud)

constexpr int a = get_a();
constexpr int b = get_b();
constexpr Point p2(a, b);
Run Code Online (Sandbox Code Playgroud)