constexpr nie gwarantuje, że kod zostanie wykonany podczas kompilacji. Można się jednak co do tego upewnić stosując static_assert, które to niejako wymusza. Ciekawostka, w C++20 zostanie wprowadzone nowe słowo kluczowe consteval, które gwarantuje że funkcja zostanie wygenerowana podczas kompilacji (przykład na samym końcu).
#include <iostream> using namespace std; class MyClass { public: constexpr MyClass(int arg) : a{arg}, b{0} { b = 4; } int a; int b; }; int main() { constexpr MyClass cobj{3}; static_assert(cobj.a == 3 and cobj.b == 4, "Doesn't match at compile time"); cout << cobj.a << " " << cobj.b << endl; }Wynik:
3 4constexpr dodaje implicit const do deklarowanych obiektów (w C++11 dodawał on również const do funkcji, jednak w C++14 z tego zrezygnowano). Jeżeli więc chcielibyśmy rozbudować klasę o metodę, która pozwala na modyfikowanie pól, kompilacja zakończy się niepowodzeniem.
#include <iostream> using namespace std; class MyClass { public: constexpr MyClass(int i) : val(i) {} constexpr void set(int num) { val = num; } constexpr int get() const { return val; } int val; }; int main() { constexpr MyClass cobj{4}; // cobj.set(44); // Error - shake powinno być const constexpr int v = cobj.get(); static_assert(v == 4, "Doesn't match at compile time"); cout << v << endl; return 0; }Wynik:
4Jedyny znany mi sposób na ominięcie tego problemu, to stworzenie nowej funkcji (także constexpr). Deklarowane w niej zmienne domyślnie będę constexpr, więc nie trzeba explicit podawać tego specyfikatora, nie zostanie dodany const, a więc będzie można zawołać metodę set() bez żadnego problemu.
#include <iostream> using namespace std; class MyClass { public: constexpr MyClass(int i) : val(i) {} constexpr void set(int num) { val = num; } constexpr int get() const { return val; } int val; }; constexpr MyClass change() { MyClass cst{4}; cst.set(56); return cst; } int main() { constexpr MyClass cst = change(); constexpr int v = cst.get(); static_assert(v == 56, "Doesn't match at compile time"); cout << v << endl; return 0; }Wynik
56Wymuszenie generowania funkcji podczas procesu kompilacji (C++20), za pomocą consteval.
#include <iostream> using namespace std; class MyClass { public: constexpr MyClass(int i) : val(i) {} constexpr void set(int num) { val = num; } constexpr int get() const { return val; } int val; }; consteval MyClass change() { MyClass cst{4}; cst.set(56); return cst; } int main() { constexpr MyClass cst = change(); constexpr int v = cst.get(); static_assert(v == 56, "Doesn't match at compile time"); cout << v << endl; return 0; }W tej chwili działa tylko z clang-iem (wersja 9.0.0-2):
$ clang++ -std=c++2a main.cpp $ ./a.out 56
Brak komentarzy:
Prześlij komentarz