简体   繁体   English

如何判断表达式是在编译时还是在运行时进行计算?

[英]How to tell if expression is evaluated at compile time or runtime?

I have a rather big Map object and I want to have a separate list that has the keys sorted. 我有一个相当大的Map对象,我希望有一个单独的列表,其中的键已经排序。 This will be used in many other source files of my poject. 这将在我的项目的许多其他源文件中使用。

The question is about how do I know when a decalaration/definition is a compile time job. 问题是如何知道decalaration / definition何时是编译时工作。 Where should I look to find if this is the case? 我应该在哪里找到是否是这种情况? I mean how to tell? 我的意思是怎么说?

In the following example, is the list in the source file a compile time job or it happens at runtime? 在以下示例中,源文件中的列表是编译时作业还是在运行时发生?

Also, is there a way that I make the sorting operation at compile time? 另外,有没有一种方法可以在编译时进行排序操作?

// global.h    
extern QMap<int, QString> G_MAP;
extern QList<int> G_MAP_SKEYS_SORTED; 

// global.cpp
QMap<int, QString> G_MAP = { /* some hand filled (static) data */ };
QList<int> G_MAP_SKEYS_SORTED = G_MAP.keys();

// main.cpp
int mian() {
  // Somewhere I do the sort
  std::sort(G_ListRegistersSorted.begin(), G_ListRegistersSorted.end());
}

An expression is evaluated at compiletime if the result is assigned to a constexpr variable, used in a static_assert or noexcept statement, or used as a template parameter. 如果将结果分配给constexpr变量,在static_assertnoexcept语句中使用,或者将其用作模板参数,则在编译时计算表达式。 This is called a constexpr context. 这称为constexpr上下文。

For example: 例如:

// Function which can calculate the fibbonacci sequence at compiletime
constexpr int fib(int n) {
    if(n == 0 || n == 1) return n;
    return fib(n - 1) + fib(n - 2); 
}

int main() {
    // This one is calculated at compiletime
    constexpr int fib10_at_compiletime = fib(10); 

    // This one is calculated at runtime 
    // (unless the compiler was really aggressive when doing optimizations)
    int fib10_at_runtime = fib(10);    
}

In order to call a function or something at compiletime, it needs to be marked constexpr . 为了在编译时调用函数或其他东西,需要将其标记为constexpr

What can you do at compiletime? 你在编译时可以做些什么?

C++11: C ++ 11:

  • Declare variables (but not modify them) 声明变量(但不能修改它们)
  • Call other constexpr functions 调用其他constexpr函数
  • Call constexpr constructors (and default ones) 调用constexpr构造函数(和默认构造函数)
  • Use carrays and std::array 使用carrays和std::array
  • Use static_asserts and stuff 使用static_asserts和东西
  • typedef and using declarations typedefusing声明

C++14 additions: C ++ 14补充:

  • You can also use lambdas now 你现在也可以使用lambdas
  • You can modify variables inside a constexpr function 您可以修改constexpr函数内的变量
  • you can have constexpr member functions that change member variables 你可以有constexpr成员函数来改变成员变量
  • you can pass references (the non-const kind) to constexpr functions 您可以将引用(非const类型)传递给constexpr函数

C++20 additions: (C++20 is coming out in 2020) C ++ 20新增内容: (C ++ 20将于2020年推出)

  • You can allocate memory now 你现在可以分配内存
  • You can call virtual functions now 您现在可以调用虚拟功能
  • You can have try-catch blocks 你可以有try-catch

Is std::sort constexpr? std::sort constexpr?

In order to use a function in a constexpr context, it must be marked constexpr (which comes with a set of restrictions on what you can do in the function; these are discussed below). 为了在constexpr上下文中使用函数,必须将其标记为constexpr(它对函数中可以执行的操作提供了一组限制;这些将在下面讨论)。 In C++11, std::sort isn't constexpr because it breaks those restrictions (and it won't be constexpr until C++20). 在C ++ 11中, std::sort不是constexpr,因为它打破了这些限制(在C ++ 20之前它不会是constexpr)。

However, if you're allowed to use C++14, you can write your own sorting function that works at compile time. 但是,如果允许使用C ++ 14,则可以编写自己的编译时在编译时运行的排序函数。

Full overview: https://en.cppreference.com/w/cpp/language/constexpr 完整概述: https //en.cppreference.com/w/cpp/language/constexpr

Also, is there a way that I make the sorting operation at compile time? 另外,有没有一种方法可以在编译时进行排序操作?

Short answer: no. 简答:不。

Long answer. 答案很长。

No because std::sort() is constexpr only from C++20 (you tagged C++11), because a void function ( std::sort() ) can't be constexpr in C++11, because QMap and QList aren't constexpr classes (if I'm not wrong), because you haven't declared GMAP and other object involved as constexpr , etc. 不,因为std::sort()只是来自C ++ 20的constexpr (你标记了C ++ 11),因为在C ++ 11中, void函数( std::sort() )不能是constexpr ,因为QMapQList不是constexpr类(如果我没有错),因为你没有声明GMAP和其他对象作为constexpr等。

But, supposing to have a MyMap class defined constexpr , a MyList class declared constexpr , a MySort() function defined constexpr , you could write something similar (starting from C++14 because in C++11 you can't write a so complex constexpr function) 但是,假设有一个MyMap类中定义constexpr ,一个MyList类中声明constexpr ,一个MySort()函数定义constexpr ,你可以写类似的东西(从C ++ 14因为在C ++ 11你不能写一个这样开始复杂的constexpr功能)

constexpr MyList foo ()
{
  MyMap mm { /* some values */ };

  MyList ml { ml.keys() };

  MySort(ml.begin(), ml.end());

  return ml;
}

// ...

constexpr auto ml_final { foo() };

Observe that ml_final is declared constexpr . 观察到ml_final被声明为constexpr

This is necessary to impose (pre C++20) the compiler to initialize the value compile-time, if possible, or give a compilation error, if impossible. 如果可能的话,这必须强制(pre C ++ 20)编译器初始化值编译时,或者如果不可能则给出编译错误。

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

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