在构造函数上指定constexpr会自动使从它创建的所有对象都是constexpr? [英] Does specifying constexpr on constructor automatically makes all objects created from it to be constexpr?

查看:123
本文介绍了在构造函数上指定constexpr会自动使从它创建的所有对象都是constexpr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是我的代码:

  class test {
public:
constexpr test

}

constexpr int operator +(const test& rhs){
return 1;
}
};



int main(){

test t; // constexpr word is not necessary
constexpr int b = t + test(); //在编译时工作!


int w = 10; // ERROR constexpr required
constexpr int c = w + 2; //需要w为constexpr
return 0;
}



我注意到它工作,即使我没有指定test为 constexpr 。我尝试复制结果通过做相同的 int 但我得到错误。具体来说,它希望我的 int w constexpr int c = w + 2; > constexpr 。我的第一次尝试是使用 test ,它的工作,因为我使用 constexpr 在构造函数已经?如果是这样,那么很好地假设所有在其构造函数上具有 constexpr 的类将导致实例化或创建的所有对象为 constexpr



奖金问题:



如果我有一个 constexpr 构造函数,是不是会做类似的事情? test * t = new test();

解决方案

有一个constexpr构造函数不会使该变量的声明自动为constexpr,因此 t 不是一个constexpr。在这种情况下发生的是你正在调用一个constexpr函数,这行:

  constexpr int b = t + test (); 

可以如下查看:

  constexpr int b = t.operator +(test()); 

那么问题是 test()是一个常量表达式,因为构造函数是constexpr,不属于C ++ 11标准部分 5.19 下的任何例外情况[ expr.const] 2


-expression是一个核心常量表达式,除非
涉及以下之一作为潜在求值的子表达式
[...]


并包含以下项目:



  • 调用除constexpr构造函数之外的函数对于字面类或constexpr函数[注意:过载解决方案
    (13.3)像往常一样应用];



[...]




  • 调用带有参数的constexpr构造函数,当被函数调用
    替换(7.1.5),不会在mem初始化器中产生构造函数调用和
    全表达式的所有常量表达式。


  • 调用将超过定义的
    递归限制(见附件B)的constexpr函数或constexpr构造函数;



我们可以通过引入一个成员变量 x 对 test / code>:

  class test {
public:
constexpr test(){

}

constexpr int operator +(const test& rhs)const {
return x + 1;
}

int x = 10;
};

尝试在 operator + 我们可以看到以下行现在失败:

  constexpr int b = t + test $ cl $ b  

从clang发出以下错误( 查看活动

):

  error:constexpr variable'b'必须用常量表达式初始化
constexpr int b = t + test(); //在编译时工作!
^ ~~~~~~~~

注意:在常量表达式中不允许读取非constexpr变量't'
return x + 1;
^

失败,因为 t 不是constexpr变量,因此其子对象也不是constexpr变量。



您的第二个示例:

  constexpr int c = w + 2; 

不工作,因为它属于草案C ++ 11标准节 5.19 [expr.const]





    [...]


    <$> b

    • 一个整数或枚举类型的glvalue,指的是具有前面初始化的非易失性const对象,初始化为
      ,具有常量表达式,或




Here is my code:

class test{
    public:
    constexpr test(){

    }

    constexpr int operator+(const test& rhs){
        return 1;
    }
};



int main(){

    test t;                         //constexpr word isn't necessary
    constexpr int b = t+test();     // works at compile time!


    int w = 10;                     // ERROR constexpr required
    constexpr int c = w + 2;        // Requires w to be constexpr
    return 0;
}

I notice that it worked even though I didn't specify test to be constexpr. I tried replicating the result by doing the same with int but i get errors. Specifically, it wants my int w inside the constexpr int c = w + 2; to be constexpr. From my first attempt which is using test, Did it work because of the reason that i used constexpr on the constructor already? If that is the case then would it good to assume that all classes that have constexpr on their constructors will result to all objects instantiated or created with it to be constexpr?

Bonus question:

If I have a constexpr constructor, is it bad to do something like ? test * t = new test(); ?

解决方案

Having a constexpr constructor does not make declarations of that variable automatically constexpr, so t is not a constexpr. What is going on in this case is that you are calling a constexpr function, this line:

constexpr int b = t+test(); 

can be viewed as follows:

constexpr int b = t.operator+( test() ); 

So then the question is whether test() is a constant expression, which it is since the constructor is constexpr and does not fall under any of the exceptions under the draft C++11 standard section 5.19 [expr.const] paragraph 2 which says:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression [...]

and includes the following bullet:

  • an invocation of a function other than a constexpr constructor for a literal class or a constexpr function [ Note: Overload resolution (13.3) is applied as usual —end note ];

[...]

  • an invocation of a constexpr constructor with arguments that, when substituted by function invocation substitution (7.1.5), do not produce all constant expressions for the constructor calls and full-expressions in the mem-initializers

  • an invocation of a constexpr function or a constexpr constructor that would exceed the implementationdefined recursion limits (see Annex B);

We can see this more readily by making some small changes to test by introducing a member variable x:

class test{
    public:
    constexpr test(){

    }

    constexpr int operator+(const test& rhs) const {
        return x + 1  ;
    }

    int x = 10 ;
};

Attempting to access it in operator + and we can see that the following line now fails:

constexpr int b = t+test();

with the following error from clang (see it live):

error: constexpr variable 'b' must be initialized by a constant expression
constexpr int b = t+test();     // works at compile time!
              ^   ~~~~~~~~

note: read of non-constexpr variable 't' is not allowed in a constant expression
    return x + 1  ;
           ^

It fails because t is not a constexpr variable and therefore its subobjects are also not constexpr variables.

Your second example:

 constexpr int c = w + 2;  

does not work because it falls under one of the exceptions in the draft C++11 standard section 5.19 [expr.const] :

  • an lvalue-to-rvalue conversion (4.1) unless it is applied to

    [...]

    • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or

这篇关于在构造函数上指定constexpr会自动使从它创建的所有对象都是constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆