What are 'constexpr' useful for?

前端 未结 4 515
说谎
说谎 2021-02-04 06:07

I really can\'t find any use of it. My first idea was that I could use it to implement \'Design by Contract\' without using macros like this:

struct S
{   
    S         


        
相关标签:
4条回答
  • 2021-02-04 06:31

    The way I see it, constexpr is a way to bring together the two C++ languages - the one that runs at runtime and the one that runs at compile time. Compile time programming is usually called meta-programming.

    First there was C, with its macros. Macros were in fact little programs that were ran by the compiler. They had if statements (called #ifdef), variables (with #define). There's even an entire scripting language that runs in compile time.

    When C++ came out, it had the C macros and nothing more. Then came the C++ templates. These introduced a different way of running compile-time code. The C++ meta-language was largely functional, allowing you to do loops with tail recursion, for example.

    In C++ 11, they've decided that meta-programming can look better, so they've introduced constexpr. Now you can write C++ functions that are also meta-functions. In C++ 14 it gets better, because the restrictions on constexpr functions have been relaxed.

    0 讨论(0)
  • 2021-02-04 06:34

    The goal of constexpr depends on the context:

    1. For objects it indicates that the object is immutable and shall be constructed at compile-time. Aside from moving operations to compile-time rather than doing them at run-time creating constexpr objects has the added advantage that they are initialize before any threads are created. As a result, their access never needs any synchronization. An example of declaring an object as constexpr would look like this:

      constexpr T value{args};
      

      Obviously, for that to work, args need to be constant expressions.

    2. For functions it indicates that calling the function can result in a constant expression. Whether the result of constexpr function call results in a constant expression depends on the arguments and the definition of the function. The immediate implication is that the function has to be inline (it will implicitly be made so). In addition, there are constraints on what can be done within such a function. For C++11 the function can have only one statement which, for non-constructors, has to be a return-statement. This restriction got relaxed in C++14. For example, the following is a definition of a constexpr function:

      constexpr int square(int value) { return value * value; }
      

    When creating constexpr object of non-built-in types the respective types will need a constexpr constructor: the generated default constructor won't work. Obviously, a constexpr constructor will need to initialize all members. A constexpr constructor could look like this:

    struct example {
        int value;
        constexpr example(int value): value(value) {}
    };
    
    int main() {
        constexpr example size{17};
        int array[size.value] = {};
    }
    

    The created constexpr values can be used everywhere a constant expression is expected.

    0 讨论(0)
  • 2021-02-04 06:36

    Here is a summary of points made by Alex Allain in his "Constexpr - Generalized Constant Expressions in C++11," which details the usefulness of constexpr:

    • First, with a constexpr specifier, the value of the function or variable can be at compile time.
    • Another benefit of the constexpr specifier is that it can replace macros with functions
    • constexpr will also benefit your template metaprogramming.

    Benefit to efficiency:

    constant expressions...allow certain computations to take place at compile time, literally while your code compiles rather than when the program itself is run. (Allain 2)

    Performance benefit: if something can be done at compile time, it will be done once, rather than every time the program runs

    Other benefits:

    Such variables and functions can then be used where only compile time constant expressions are allowed. A constexpr specifier used in an object declaration implies const. A constexpr specifier used in an function declaration implies inline.(CPP 1)

    Rules for constexpr functions:

    1. It must consist of single return statement (with a few exceptions)
    2. It can call only other constexpr functions
    3. It can reference only constexpr global variables (Allain 6)

    Rules for constexpr constructors:

    1. each of its parameters must be literal type
    2. the class must have no virtual base classes
    3. the constructor must not have a function-try-block (CPP 6)

    Citations

    Allain, Alex, "Constexpr - Generalized Constant Expressions in C++11", Unspecified Date, "http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html"

    CPP, "Constexpr Specifier", 16 December 2014, http://en.cppreference.com/w/cpp/language/constexpr


    EDIT: Sorry, It was my fault to make it seem like I was the author of these points, so I have corrected myself, changed various parts, and added citations to avoid plagiarism.

    0 讨论(0)
  • 2021-02-04 06:45

    Answer of " Can someone give me some insight why constexpr keyword was being introduced?"

    Modern C++ supports two types of immutability.

    1) const

    2) constexpr.

    constexper will be evaluated at the compile time. It is used to specify constness and allows placement of data in the memory where it might be corrupted.

    Example 1:

    void UseConstExpr(int temp)
    {
        // This code snippet is OK
        constexpr int y = max + 300;
        std::cout << y << std::endl;
        // This code snippet gives compilation error
        // [ expression must have a constant value]
        constexpr int z = temp + 300;
    
    }
    

    Example 2:

    int addVector(const std::vector<int>& inVect)
    {
        int sum = 0;
        for ( auto& vec : inVect)
        {
            sum += vec;
        }
        std::cout << sum << std::endl;
        return sum;
    }
    
    int main()
    {
        // vInt is not constant
        std::vector<int> vInt = { 1,2,3,4,5,6 }; 
        // This code snippet is OK
        // because evaluated at run time
        const int iResult = addVector(vInt);
        // Compiler throws below error
        // function call must have a constant value in a constant expression
        // because addVector(vInt) function is not a constant expression
        constexpr int iResult = addVector(vInt);
        return 0;
    }
    

    Note: above source code are compiled on VS2015

    0 讨论(0)
提交回复
热议问题