简体   繁体   English

我可以创建编译时变量对象吗?

[英]C++ - Can I create compile-time variable object?

I was using constexpr recently but I just realized I used it wrong. 我最近在使用constexpr,但我只是意识到我用错了。 I am curious whether I can create a compile-time variable (or variable object). 我很好奇我是否可以创建一个编译时变量(或变量对象)。
A constexpr definition from cppreference.com tells us: 来自cppreference.com的constexpr定义告诉我们:

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. constexpr说明符声明可以在编译时评估函数或变量的值。

So why is following code incorrect? 那么为什么下面的代码不正确?

#include <iostream>

int main()
{
    constexpr int x = 30;
    x += 10;
    std::cout << x;
}

This integer can be perfectly evaluated in compile-time. 该整数可以在编译时完美评估。 I know compilers can optimize such a variable without constexpr modifier, but what if I want to have a compile-time object? 我知道编译器可以在没有constexpr修饰符的情况下优化此类变量,但是如果我想拥有一个编译时对象怎么办?

#include <iostream>

class ctFoo {
public:
    ctFoo()
        : value{ 0 }
    {
    }
    int accumulate(int value_) {
        return (value += value_), value;
    }
    int value;
};

int main()
{
    ctFoo foo;
    std::cout << foo.accumulate(100);
}

What certainty I have, that this code will be evaluated in compile-time? 我有什么把握可以在编译时评估此代码? I am asking this, because I am currently writing some Vector2 and Vector3 maths and I wanted to create such implementation, that will be able to handle compile-time and run-time calculations. 我之所以这么问,是因为我目前正在编写一些Vector2和Vector3数学,并且我想创建这样的实现,它将能够处理编译时和运行时计算。 Is it even possible? 可能吗
Thanks. 谢谢。

Edit 编辑

As max66 pointed out, constexpr implies const, but I am asking: why so? 正如max66所指出的,constexpr隐含const,但是我在问:为什么这样? Modern compilers should be able to deduce its value in compile-time. 现代编译器应该能够在编译时推断出它的价值。 Also, I know I can simply create another constexpr constant (ad. top-most code example), but my question refer to more complicated code. 另外,我知道我可以简单地创建另一个constexpr常量(广告最上面的代码示例),但是我的问题是针对更复杂的代码。

So why is following code incorrect? 那么为什么下面的代码不正确?

 #include <iostream> int main() { constexpr int x = 30; x += 10; std::cout << x; } 

constexpr implies const . constexpr暗示const You need to constrain this to a constexpr context: 您需要将此约束到constexpr上下文中:

constexpr int foo() {
    int x = 30;
    x += 10;
    return x;
}

But what if I want to have a compile-time object? 但是,如果我想拥有一个编译时对象怎么办?

 #include <iostream> class ctFoo { public: ctFoo() : value{ 0 } { } int accumulate(int value_) { return (value += value_), value; } int value; }; 

Give it constexpr support: 给它constexpr支持:

constexpr ctFoo() : value{ 0 }

constexpr int accumulate(int value_) {
    value += value_;
    return value;
}

The guarantees you now have are that if your ctFoo object is a constant expression and you call accumulate in a constexpr context like the foo function example, then you can use the result at compile-time. 现在的保证是,如果您的ctFoo对象是一个常量表达式,并且您在constexpr上下文(如foo函数示例)中调用accumulate ,那么您可以在编译时使用结果。 For example: 例如:

constexpr int foo() {
    ctFoo f;
    f.accumulate(10);
    return f.value;
}

static_assert(foo() == 10);

Or: 要么:

constexpr void accumulate(ctFoo& f) {
    f.accumulate(10);
}

constexpr int foo() {
    ctFoo f;
    accumulate(f);
    return f.value;
}

static_assert(foo() == 10);

The key thing to remember here is that runtime evaluation is also an option. 这里要记住的关键是,运行时评估也是一种选择。 If I set some ctFoo 's value to a runtime value (eg, user input), then there's no way an accumulate call could happen at compile-time. 如果我将ctFoovalue设置为运行时值(例如,用户输入),那么在编译时就不可能发生accumulate调用。 But that's okay - the same code works in both contexts. 但这没关系-相同的代码在两种情况下均有效。

You need to continue reading: 您需要继续阅读:

A constexpr specifier used in an object declaration implies const . 对象声明中使用的constexpr说明符暗含const

You cannot change a constexpr , that's the whole point of you being able to use it in constant expressions. 您不能更改constexpr ,这就是您可以在常量表达式中使用它的全部目的。

The next thing to consider is that you seem to be mixing two different contexts. 接下来要考虑的是,您似乎正在混合两种不同的上下文。 I have no doubt that compilers will be able to optimize your last example completely away, but that is something else that what constexpr does. 我毫不怀疑,编译器将能够完全优化您的最后一个示例,但这就是constexpr所做的其他事情。 The keyword says that what it denotes can be evaluated at compile time, but it doesn't have to be. 关键字表示它的含义可以在编译时进行评估,但不一定必须如此。 So you can write a constexpr function, with everything in it being possibly evaluated at compile time, and still have it work at run time. 因此,您可以编写一个constexpr函数,其中的所有内容都可以在编译时进行评估,并且仍然可以在运行时运行。

The only time you can really have objects that can evaluated at compile time (so no optimizer) and that you can modify is when you are in a compile time context. 真正只有在编译时就可以评估的对象(因此没有优化程序),并且您可以修改的唯一时间是在编译时上下文中。 You are in such a context for example in a constexpr function: 您处于这样的上下文中,例如constexpr函数中:

constexpr int foo() {
    int a = 10;
    ++a; // I can modify a.
    return a;
    // even if I did this: int Array[foo()];
}

But you have no such ability in a normal function, the language just doesn't allow it. 但是您在常规功能中没有这种能力,而该语言只是不允许这样做。

So, to answer your questions: 因此,回答您的问题:

What certainty I have, that this code will be evaluated in compile-time? 我有什么把握可以在编译时评估此代码?

You don't have any, because you aren't using constexpr . 您没有任何东西,因为您没有使用constexpr And even then, if you are calling the constexpr function somewhere that doesn't require a compile time evaluation, the function might get called at run time, 即使这样,如果您在不需要编译时求值的地方调用constexpr函数,则该函数可能会在运行时被调用,

Is it even possible? 可能吗

Sure, as said, you create a constexpr function, which will get evaluated at compile time if the need arises. 可以肯定的是,您已经创建了constexpr函数,如果需要,它将在编译时进行评估。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM