Share via


constexpr (C++)

Klíčové slovo constexpr bylo zavedeno v jazyce C++11 a vylepšeno v jazyce C++14. To znamená constvýraz ant. Podobně jako constu proměnných se dá použít: Při každém pokusu o modifikováníifhodnoty se vyvolá chyba kompilátoru. Na rozdíl od const, constexpr lze také použít na funkce a ructory třídy const. constexpr označuje, že hodnota nebo návratová hodnota je constant a pokud je to možné, vypočítá se v době kompilace.

constexpr Celočíselnou hodnotu lze použít všude, kde const je požadováno celé číslo, například v argumentech šablony a deklarací pole. A když se hodnota vypočítá v době kompilace místo doby běhu, pomůže vašemu programu běžet rychleji a využívat méně paměti.

Aby se omezila složitost výpočtů v době constkompilace a jejich potenciální dopady na čas kompilace, standard C++14 vyžaduje, aby typy ve constvýrazech ant byly literální typy.

Syntaxe

constexprliteral-typeidentifier=constant-expression;
constexprliteral-typeidentifier{constant-expression};
constexprliteral-typeidentifier(params);
constexprctor(params);

Parametry

params
Jeden nebo více parametrů, z nichž každý musí být literálový typ a musí být sám výrazem constant.

Vrácená hodnota

Proměnná constexpr nebo funkce musí vracet typ literálu.

constexpr Proměnné

Primární difference mezi const proměnnými a constexpr proměnnými spočívá v tom, že inicializace const proměnné může být odložena do doby běhu. Proměnná constexpr musí být inicializována v době kompilace. Všechny constexpr proměnné jsou const.

  • Proměnnou lze deklarovat pomocí constexpr, pokud má typ literálu a je inicializován. Pokud je inicializace performed ructor const, constmusí být ructor deklarován jako constexpr.

  • Odkaz může být deklarován, jako constexpr když jsou splněny obě tyto podmínky: Odkazovaný objekt je inicializován výrazem constant a všechny implicitní převody vyvolané během inicializace jsou také constant výrazy.

  • Všechny deklarace constexpr proměnné nebo funkce musí mít constexpr specifikátorif.

constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression

constexpr – funkce

Funkce constexpr je funkce, jejíž návratová hodnota je v době kompilace kompuovat, když ho vyžaduje náročný kód. Použití kódu vyžaduje návratovou hodnotu v době kompilace k inicializaci constexpr proměnné nebo k poskytnutí argumentu šablony bez typu. Pokud jsou constexpr argumenty hodnoty, constexpr funkce vytvoří ant času constkompilace. Při zavolání s neconstexpr argumenty nebo když není její hodnota v době kompilace nutná, vytvoří hodnotu za běhu, jako je běžná funkce. (Toto duální chování vás šetří od nutnosti psát constexpr a neverzeconstexpr stejné funkce.)

Funkce constexpr nebo constructor je implicitně inline.

Následující pravidla platí pro constexpr funkce:

  • constexpr Funkce musí přijímat a vracet pouze literály.

  • constexpr Funkce může být rekurzivní.

  • Before C++20, constexpr funkce nemůže být virtuální a constructor nelze definovat, jako constexpr když má nadřazená třída všechny virtuální základní třídy. V jazyce C++20 a novější constexpr může být funkce virtuální. Visual Studio 2019 verze 16.10 a novější verze podporují constexpr virtuální funkce, když specifikujeteifmožnost kompilátoru /std:c++20 nebo novější.

  • Tělo může být definováno jako = default nebo = delete.

  • Tělo nesmí obsahovat žádné goto příkazy ani try bloky.

  • Explicitní specializace jinéconstexpr šablony může být deklarována takto constexpr:

  • Explicitní specializace constexpr šablony nemusí být constexprtaké:

Následující pravidla platí pro constexpr funkce v sadě Visual Studio 2017 a novější:

  • Může obsahovat if a switch příkazy a všechny příkazy smyčky, včetně forpříkazů založených na forwhilerozsahu a do-while.

  • Může obsahovat deklarace místních proměnných, ale proměnná musí být inicializována. Musí to být literálový typ a nesmí být static místní nebo vlákno. Místně deklarovaná proměnná nemusí být consta může ztlumit.

  • constexpr Nečlennástatic funkce nemusí být implicitně const.

constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

Tip

Při ladění neoptimalovaného sestavení Ladění v ladicím programu sady Visual Studio můžete zjistit, jestli se funkce v době kompilace vyhodnocuje, tím, že constexpr do ní umístíte zarážku. Pokud je zarážka nalezena, funkce byla volána za běhu. Pokud ne, funkce byla volána v době kompilace.

Externí constexpr

Možnost kompilátoru /Zc:externConstexpr způsobí, že kompilátor použije externí propojení na proměnné deklarované pomocí extern constexpr. V dřívějších verzích sady Visual Studio buď ve výchozím nastavení, nebo když je parametr /Zc:externConstexpr- specifikovanýif, visual Studio použije interní propojení s constexpr proměnnými i v případě, že extern se použije klíčové slovo. Možnost /Zc:externConstexpr je dostupná od sady Visual Studio 2017 Update 15.6 a je ve výchozím nastavení vypnutá. Možnost /permissive- nepovoluje /Zc:externConstexpr.

Příklad

Následující příklad ukazuje constexpr proměnné, funkce a uživatelem definovaný typ. V posledním příkazu v main()členové constexpr funkci GetValue() je volání za běhu, protože hodnota nemusí být známa v době kompilace.

// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>

using namespace std;

// Pass by value
constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp2(x * x, n / 2) :
        exp2(x * x, (n - 1) / 2) * x;
}

// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
    return N;
}

// Recursive constexpr function
constexpr int fac(int n)
{
    return n == 1 ? 1 : n * fac(n - 1);
}

// User-defined type
class Foo
{
public:
    constexpr explicit Foo(int i) : _i(i) {}
    constexpr int GetValue() const
    {
        return _i;
    }
private:
    int _i;
};

int main()
{
    // foo is const:
    constexpr Foo foo(5);
    // foo = Foo(6); //Error!

    // Compile time:
    constexpr float x = exp(5, 3);
    constexpr float y { exp(2, 5) };
    constexpr int val = foo.GetValue();
    constexpr int f5 = fac(5);
    const int nums[] { 1, 2, 3, 4 };
    const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };

    // Run time:
    cout << "The value of foo is " << foo.GetValue() << endl;
}

Požadavky

Sada Visual Studio 2015 nebo novější.

Viz také

Deklarace a definice
const