V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
paparika
V2EX  ›  C

关于 constexpr 的疑问

  •  
  •   paparika · Jun 6, 2018 · 2802 views
    This topic created in 2883 days ago, the information mentioned may be changed or developed.

    class TestClass1{ public:

    static constexpr int getInt(){return 0;};
    
    static constexpr int y = getInt();//why it's wrong?
    
    TestClass1(){}
    

    };

    编译失败了,why?

    16 replies    2018-06-08 17:49:37 +08:00
    enenaaa
        1
    enenaaa  
       Jun 6, 2018
    constexpr 也要遵守基本法。c++类成员声明不接受赋值啊。
    paparika
        2
    paparika  
    OP
       Jun 6, 2018
    @enenaaa static constexpr int y = 0; 能过,这个算初始化不算赋值?
    enenaaa
        3
    enenaaa  
       Jun 6, 2018
    不好意思, 我忘了 static 变量是可以的
    wens07
        4
    wens07  
       Jun 6, 2018
    getInt 是一个 expresion,这样不行的吧
    paparika
        5
    paparika  
    OP
       Jun 6, 2018
    编译器报的 error: ‘ static constexpr int TestClass1::getInt()’ called in a constant expression
    wwqgtxx
        6
    wwqgtxx  
       Jun 6, 2018
    GCC 的提示说的挺清楚的了吧
    error: 'static constexpr int TestClass1::getInt()' called in a constant expression before its definition is complete
    wwqgtxx
        7
    wwqgtxx  
       Jun 6, 2018
    也就是说这样写是可行的
    class TestClass1{ public:

    static constexpr int getInt(){return 0;};

    TestClass1(){}
    };

    class TestClass2{ public:

    static constexpr int y = TestClass1::getInt();//why it's wrong?

    TestClass2(){}
    };
    paparika
        8
    paparika  
    OP
       Jun 6, 2018
    @wwqgtxx 不太理解,信息给足了啊,怎么还不算 complete,有反例吗
    wwqgtxx
        9
    wwqgtxx  
       Jun 6, 2018
    @paparika 他的意思是只能在类的定义完成之后才能以 constexpr 的形式调用,至于为什么,你可能需要翻翻 C++的标准了
    paparika
        10
    paparika  
    OP
       Jun 6, 2018
    @wwqgtxx 暂时这么强行理解了,thx
    vsomeone
        11
    vsomeone  
       Jun 6, 2018
    https://stackoverflow.com/questions/11522399/constexpr-initializing-static-member-using-static-function:

    The most likely reason for this is that constexpr variables have to be available as compile-time constant expressions from inside the bodies of member functions, so the variable initializers are completely defined before the function bodies -- which means the function is still incomplete (undefined) in the context of the initializer, and then this rule kicks in, making the expression not be a constant expression.

    大致意思就是,由于 constexpr 必须是 compile-time known 的,所以它们的 initializer 定义位于它们所在的 function/class 之外。因此,你的代码等价于:

    ```c++

    constexpr int TestClass1::y = initializer_for_y();

    class TestClass1{ public:

    static constexpr int getInt(){return 0;};
    static constexpr int y;//why it's wrong?
    TestClass1(){}
    };
    ```

    但是在 initializer_for_y() 试着调用 getInt() 的时候 TestClass1 尚未定义。这也就是为什么编译器会报告:
    note: undefined function 'getInt' cannot be used in a constant expression
    gnaggnoyil
        12
    gnaggnoyil  
       Jun 6, 2018
    @paparika 然而你现在只能这样强行理解……因为事实上标准中没有任何字句显式要求成员函数的类内定义一定不能在类的内部起效,而只是要求在类内部的时候类是一个不完全类型……换句话说标准没有要求你这种写法一定是错的.事实上你会发现在 Clang 和 GCC 下只要给 TestClass1 加一个模板参数编译错误就嗷的一声不见了…… https://wandbox.org/permlink/MiclIS7tSl4qR91C

    我搜了一下发现 CWG1626( http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1626)提到了这个问题,然而很明显 WG21 至今仍在无视这个 2013 年就提出来的 CWG...
    gnaggnoyil
        13
    gnaggnoyil  
       Jun 6, 2018
    @gnaggnoyil 干……发错.演示地址是这个: https://wandbox.org/permlink/hDmeC12PUHPRmoPp
    paparika
        14
    paparika  
    OP
       Jun 7, 2018
    @vsomeone
    @gnaggnoyil

    厉害厉害!
    alqaz
        15
    alqaz  
       Jun 8, 2018
    @gnaggnoyil 是不是可以理解成编译器处理模板在处理 constexpr 之前,加了模板参数之后,先扫描一边 TestClass1,此时编译器对 TestClass1::getInt() constexpr 函数已经知道了。然后处理 constper 相关的计算也就可以了。
    gnaggnoyil
        16
    gnaggnoyil  
       Jun 8, 2018
    没仔细读 GCC 和 Clang 的源码.不过它们都是支持 two-phase lookup 的而你理解的这种行为按照 two-phase lookup 的要求是 ill-formed,虽然没要求有 diagnostics...
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3260 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 13:49 · PVG 21:49 · LAX 06:49 · JFK 09:49
    ♥ Do have faith in what you're doing.