constexpr
docker 起動
$ docker run -v /Users/ogawakiyoshi/n4910:/Users/ogawakiyoshi/n4910 -it kaizenjapan/n4910 /bin/bash
cpp1.cpp
constexpr int f();
constexpr bool b1 = noexcept(f()); // false, undefined constexpr function
constexpr int f() { return 0; }
constexpr bool b2 = noexcept(f()); // true, f() is a constant expression
void f(int& i) // not a constexpr function
{
i = 0;
}
constexpr void g(int& i) // well-formed since C++23
{
f(i); // unconditionally calls f, cannot be a constant expression
}
static constexpr int const& x = 42; // constexpr reference to a const int object
// (the object has static storage duration
// due to life extension by a static reference)
int main()
{
cout << "constexpr" << endl;
return EXIT_SUCCESS;;
}
Compile
$ clang++ cpp1.cpp -std=03 -o cpp1l -I. -Wall
cpp1.cpp:6:1: error: unknown type name 'constexpr'
constexpr int f2();
^
cpp1.cpp:7:1: error: unknown type name 'constexpr'
constexpr bool b1 = noexcept(f2()); // false, undefined constexpr function
^
cpp1.cpp:8:1: error: unknown type name 'constexpr'
constexpr int f2() { return 0; }
^
cpp1.cpp:9:1: error: unknown type name 'constexpr'
constexpr bool b2 = noexcept(f2()); // true, f() is a constant expression
^
cpp1.cpp:14:1: error: unknown type name 'constexpr'
constexpr void g(int& i) // well-formed since C++23
^
cpp1.cpp:18:8: error: unknown type name 'constexpr'
static constexpr int const& x = 42; // constexpr reference to a const int object
^
6 errors generated.
$ clang++ cpp1.cpp -std=2b -o cpp1l -I. -Wall
cpp1.cpp:7:16: warning: unused variable 'b1' [-Wunused-const-variable]
constexpr bool b1 = noexcept(f2()); // false, undefined constexpr function
^
cpp1.cpp:9:16: warning: unused variable 'b2' [-Wunused-const-variable]
constexpr bool b2 = noexcept(f2()); // true, f() is a constant expression
^
cpp1.cpp:18:29: warning: unused variable 'x' [-Wunused-variable]
static constexpr int const& x = 42; // constexpr reference to a const int object
^
3 warnings generated.
constexpr
$ g++ cpp1.cpp -std=03 -o cpp1g -I. -Wall
cpp1.cpp:6:1: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
6 | constexpr int f2();
| ^~~~~~~~~
cpp1.cpp:7:21: warning: identifier 'noexcept' is a keyword in C++11 [-Wc++11-compat]
7 | constexpr bool b1 = noexcept(f2()); // false, undefined constexpr function
| ^~~~~~~~
cpp1.cpp:6:1: error: 'constexpr' does not name a type
6 | constexpr int f2();
| ^~~~~~~~~
cpp1.cpp:6:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp1.cpp:7:1: error: 'constexpr' does not name a type
7 | constexpr bool b1 = noexcept(f2()); // false, undefined constexpr function
| ^~~~~~~~~
cpp1.cpp:7:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp1.cpp:8:1: error: 'constexpr' does not name a type
8 | constexpr int f2() { return 0; }
| ^~~~~~~~~
cpp1.cpp:8:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp1.cpp:9:1: error: 'constexpr' does not name a type
9 | constexpr bool b2 = noexcept(f2()); // true, f() is a constant expression
| ^~~~~~~~~
cpp1.cpp:9:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp1.cpp:14:1: error: 'constexpr' does not name a type
14 | constexpr void g(int& i) // well-formed since C++23
| ^~~~~~~~~
cpp1.cpp:14:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp1.cpp:18:8: error: 'constexpr' does not name a type
18 | static constexpr int const& x = 42; // constexpr reference to a const int object
| ^~~~~~~~~
cpp1.cpp:18:8: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
$ g++ cpp1.cpp -std=2b -o cpp1g -I. -Wall
cpp1.cpp: In function 'constexpr void g(int&)':
cpp1.cpp:16:6: error: call to non-'constexpr' function 'void f(int&)'
16 | f(i); // unconditionally calls f, cannot be a constant expression
| ~^~~
cpp1.cpp:10:6: note: 'void f(int&)' declared here
10 | void f(int& i) // not a constexpr function
| ^
cpp2.cpp
#include <iostream>
#include <stdexcept>
// C++11 constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
return n <= 1 ? 1 : (n * factorial(n - 1));
}
// C++14 constexpr functions may use local variables and loops
#if __cplusplus >= 201402L
constexpr int factorial_cxx14(int n)
{
int res = 1;
while (n > 1)
res *= n--;
return res;
}
#endif // C++14
// literal class
class conststr
{
const char* p;
std::size_t sz;
public:
template<std::size_t N>
constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
// constexpr functions signal errors by throwing exceptions
// in C++11, they must do so from the conditional operator ?:
constexpr char operator[](std::size_t n) const
{
return n < sz ? p[n] : throw std::out_of_range("");
}
constexpr std::size_t size() const { return sz; }
};
// C++11 constexpr functions had to put everything in a single return statement
// (C++14 doesn't have that requirement)
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
std::size_t c = 0)
{
return n == s.size() ? c :
'a' <= s[n] && s[n] <= 'z' ? countlower(s, n + 1, c + 1) :
countlower(s, n + 1, c);
}
// output function that requires a compile-time constant, for testing
template<int n>
struct constN
{
constN() { std::cout << n << '\n'; }
};
int main()
{
std::cout << "4! = " ;
constN<factorial(4)> out1; // computed at compile time
volatile int k = 8; // disallow optimization using volatile
std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
std::cout << "the number of lowercase letters in \"Hello, world!\" is ";
constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
constexpr int a[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
constexpr int length_a = sizeof(a)/sizeof(int); // std::size(a) in C++17,
// std::ssize(a) in C++20
std::cout << "array of length " << length_a << " has elements: ";
for (int i = 0; i < length_a; ++i)
std::cout << a[i] << " ";
}
Compile & Go
$ clang++ cpp2.cpp -std=03 -o cpp2l -I. -Wall
cpp2.cpp:5:1: error: unknown type name 'constexpr'
constexpr int factorial(int n)
^
cpp2.cpp:28:5: error: unknown type name 'constexpr'; did you mean 'conststr'?
constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
^~~~~~~~~
conststr
cpp2.cpp:22:7: note: 'conststr' declared here
class conststr
^
cpp2.cpp:28:15: error: constructor cannot have a return type
constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
~~~~~~~~~ ^~~~~~~~
cpp2.cpp:32:5: error: unknown type name 'constexpr'; did you mean 'conststr'?
constexpr char operator[](std::size_t n) const
^~~~~~~~~
conststr
cpp2.cpp:22:7: note: 'conststr' declared here
class conststr
^
cpp2.cpp:32:15: error: cannot combine with previous 'type-name' declaration specifier
constexpr char operator[](std::size_t n) const
^
cpp2.cpp:37:5: error: unknown type name 'constexpr'; did you mean 'conststr'?
constexpr std::size_t size() const { return sz; }
^~~~~~~~~
conststr
cpp2.cpp:22:7: note: 'conststr' declared here
class conststr
^
cpp2.cpp:37:20: error: non-friend class member 'size_t' cannot have a qualified name
constexpr std::size_t size() const { return sz; }
~~~~~^
cpp2.cpp:37:20: error: field has incomplete type 'conststr'
cpp2.cpp:22:7: note: definition of 'conststr' is not complete until the closing '}'
class conststr
^
cpp2.cpp:37:26: error: expected ';' at end of declaration list
constexpr std::size_t size() const { return sz; }
^
;
cpp2.cpp:34:16: error: no viable conversion from returned value of type 'const char' to function return type 'conststr'
return n < sz ? p[n] : throw std::out_of_range("");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cpp2.cpp:22:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char' to 'const conststr &' for 1st argument
class conststr
^
cpp2.cpp:42:1: error: unknown type name 'constexpr'
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
^
cpp2.cpp:42:22: error: expected ';' after top level declarator
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
^
;
cpp2.cpp:60:5: error: no template named 'constN'
constN<factorial(4)> out1; // computed at compile time
^
cpp2.cpp:66:12: error: use of undeclared identifier 'countlower'
constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
^
cpp2.cpp:66:41: error: use of undeclared identifier 'out2'; did you mean 'out1'?
constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
^~~~
out1
cpp2.cpp:60:26: note: 'out1' declared here
constN<factorial(4)> out1; // computed at compile time
^
cpp2.cpp:66:5: error: use of undeclared identifier 'constN'; did you mean 'const'?
constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
^~~~~~
const
cpp2.cpp:66:5: error: expected unqualified-id
cpp2.cpp:68:5: error: unknown type name 'constexpr'
constexpr int a[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
^
cpp2.cpp:69:5: error: unknown type name 'constexpr'
constexpr int length_a = sizeof(a)/sizeof(int); // std::size(a) in C++17,
^
19 errors generated.
$ clang++ cpp2.cpp -std=2b -o cpp2l -I. -Wall
4! = 24
8! = 40320
the number of lowercase letters in "Hello, world!" is 9
array of length 12 has elements: 0 1 2 3 4 5 6 7 8 0 0 0
$ g++ cpp2.cpp -std=03 -o cpp2g -I. -Wall
cpp2.cpp:5:1: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
5 | constexpr int factorial(int n)
| ^~~~~~~~~
cpp2.cpp:5:1: error: 'constexpr' does not name a type
cpp2.cpp:5:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp2.cpp:28:5: error: 'constexpr' does not name a type; did you mean 'conststr'?
28 | constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
| ^~~~~~~~~
| conststr
cpp2.cpp:28:5: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp2.cpp:32:5: error: 'constexpr' does not name a type; did you mean 'conststr'?
32 | constexpr char operator[](std::size_t n) const
| ^~~~~~~~~
| conststr
cpp2.cpp:32:5: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp2.cpp:37:5: error: 'constexpr' does not name a type; did you mean 'conststr'?
37 | constexpr std::size_t size() const { return sz; }
| ^~~~~~~~~
| conststr
cpp2.cpp:37:5: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp2.cpp:42:1: error: 'constexpr' does not name a type; did you mean 'conststr'?
42 | constexpr std::size_t countlower(conststr s, std::size_t n = 0,
| ^~~~~~~~~
| conststr
cpp2.cpp:42:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
cpp2.cpp: In function 'int main()':
cpp2.cpp:60:23: error: a function call cannot appear in a constant-expression
60 | constN<factorial(4)> out1; // computed at compile time
| ^
cpp2.cpp:60:24: error: template argument 1 is invalid
60 | constN<factorial(4)> out1; // computed at compile time
| ^
cpp2.cpp:63:33: error: 'factorial' was not declared in this scope
63 | std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
| ^~~~~~~~~
cpp2.cpp:66:38: error: a function call cannot appear in a constant-expression
66 | constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
| ^
cpp2.cpp:66:39: error: template argument 1 is invalid
66 | constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
| ^
cpp2.cpp:68:5: error: 'constexpr' was not declared in this scope; did you mean 'conststr'?
68 | constexpr int a[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
| ^~~~~~~~~
| conststr
cpp2.cpp:69:14: error: expected ';' before 'int'
69 | constexpr int length_a = sizeof(a)/sizeof(int); // std::size(a) in C++17,
| ^~~~
| ;
cpp2.cpp:71:40: error: 'length_a' was not declared in this scope
71 | std::cout << "array of length " << length_a << " has elements: ";
| ^~~~~~~~
cpp2.cpp:73:22: error: 'a' was not declared in this scope
73 | std::cout << a[i] << " ";
| ^
cpp2.cpp:60:26: warning: unused variable 'out1' [-Wunused-variable]
60 | constN<factorial(4)> out1; // computed at compile time
| ^~~~
cpp2.cpp:66:41: warning: unused variable 'out2' [-Wunused-variable]
66 | constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
| ^~~~
$ g++ cpp2.cpp -std=2b -o cpp2g -I. -Wall
4! = 24
8! = 40320
the number of lowercase letters in "Hello, world!" is 9
array of length 12 has elements: 0 1 2 3 4 5 6 7 8 0 0 0
c1.cpp
ソース:上記
// https://cpprefjp.github.io/lang/cpp11/constexpr.html
#include <cassert>
constexpr int square(int x)
{
return x * x;
}
int main()
{
constexpr int compile_time_result = square(3);
static_assert(compile_time_result == 9, "result must be 9");
int runtime_result = square(3);
assert(runtime_result == 9);
}
コンパイル
# ../clgc.sh c1
$ clang++ c1.cpp -std=03 -o c1l -I. -Wall
c1.cpp:3:1: error: unknown type name 'constexpr'
constexpr int square(int x)
^
c1.cpp:10:3: error: unknown type name 'constexpr'
constexpr int compile_time_result = square(3);
^
2 errors generated.
$ clang++ c1.cpp -std=2b -o c1l -I. -Wall
$ g++ c1.cpp -std=03 -o c1g -I. -Wall
c1.cpp:3:1: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
3 | constexpr int square(int x)
| ^~~~~~~~~
c1.cpp:11:3: warning: identifier 'static_assert' is a keyword in C++11 [-Wc++11-compat]
11 | static_assert(compile_time_result == 9, "result must be 9");
| ^~~~~~~~~~~~~
c1.cpp:3:1: error: 'constexpr' does not name a type
3 | constexpr int square(int x)
| ^~~~~~~~~
c1.cpp:3:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c1.cpp: In function 'int main()':
c1.cpp:10:3: error: 'constexpr' was not declared in this scope
10 | constexpr int compile_time_result = square(3);
| ^~~~~~~~~
c1.cpp:11:17: error: 'compile_time_result' was not declared in this scope
11 | static_assert(compile_time_result == 9, "result must be 9");
| ^~~~~~~~~~~~~~~~~~~
c1.cpp:11:3: error: 'static_assert' was not declared in this scope
11 | static_assert(compile_time_result == 9, "result must be 9");
| ^~~~~~~~~~~~~
c1.cpp:13:24: error: 'square' was not declared in this scope
13 | int runtime_result = square(3);
| ^~~~~~
$ g++ c1.cpp -std=2b -o c1g -I. -Wall
出力する。
// https://cpprefjp.github.io/lang/cpp11/constexpr.html
#include <iostream>
#include <cassert>
#include <cstdlib>
using namespace std;
constexpr int square(int x)
{
return x * x;
}
int main()
{
constexpr int compile_time_result = square(3);
cout << compile_time_result << endl;
static_assert(compile_time_result == 9, "result must be 9");
cout << compile_time_result << endl;
int runtime_result = square(3);
assert(runtime_result == 9);
cout << runtime_result << endl;
return EXIT_SUCCESS;;
}
コンパイル結果
$ clang++ c1a.cpp -std=03 -o c1al -I. -Wall
c1a.cpp:8:1: error: unknown type name 'constexpr'
constexpr int square(int x)
^
c1a.cpp:15:3: error: unknown type name 'constexpr'
constexpr int compile_time_result = square(3);
^
2 errors generated.
$ clang++ c1a.cpp -std=2b -o c1al -I. -Wall
9
9
9
$ g++ c1a.cpp -std=03 -o c1ag -I. -Wall
c1a.cpp:8:1: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
8 | constexpr int square(int x)
| ^~~~~~~~~
c1a.cpp:18:3: warning: identifier 'static_assert' is a keyword in C++11 [-Wc++11-compat]
18 | static_assert(compile_time_result == 9, "result must be 9");
| ^~~~~~~~~~~~~
c1a.cpp:8:1: error: 'constexpr' does not name a type
8 | constexpr int square(int x)
| ^~~~~~~~~
c1a.cpp:8:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c1a.cpp: In function 'int main()':
c1a.cpp:15:3: error: 'constexpr' was not declared in this scope
15 | constexpr int compile_time_result = square(3);
| ^~~~~~~~~
c1a.cpp:16:13: error: 'compile_time_result' was not declared in this scope
16 | cout << compile_time_result << endl;
| ^~~~~~~~~~~~~~~~~~~
c1a.cpp:18:3: error: 'static_assert' was not declared in this scope
18 | static_assert(compile_time_result == 9, "result must be 9");
| ^~~~~~~~~~~~~
c1a.cpp:20:24: error: 'square' was not declared in this scope
20 | int runtime_result = square(3);
| ^~~~~~
$ g++ c1a.cpp -std=2b -o c1ag -I. -Wall
9
9
9
意味のある出力
これから検討
c2.cpp
constexpr int min(int a, int b)
{
// 条件分岐には条件演算子?:を使用する
return a < b ? a : b;
}
constexpr int factorial(int n)
{
// ループには再帰を使用する
return n == 0 ? 1 : n * factorial(n - 1);
}
int main()
{
constexpr int min_val = min(2, 3);
static_assert(min_val == 2, "result must be 2");
constexpr int factorial_val = factorial(5);
static_assert(factorial_val == 120, "result muse be 120");
}
コンパイル
$ clang++ c2.cpp -std=03 -o c2l -I. -Wall
c2.cpp:1:1: error: unknown type name 'constexpr'
constexpr int min(int a, int b)
^
c2.cpp:7:1: error: unknown type name 'constexpr'
constexpr int factorial(int n)
^
c2.cpp:15:3: error: unknown type name 'constexpr'
constexpr int min_val = min(2, 3);
^
c2.cpp:18:3: error: unknown type name 'constexpr'
constexpr int factorial_val = factorial(5);
^
4 errors generated.
$ clang++ c2.cpp -std=2b -o c2l -I. -Wall
$ g++ c2.cpp -std=03 -o c2g -I. -Wall
c2.cpp:1:1: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
1 | constexpr int min(int a, int b)
| ^~~~~~~~~
c2.cpp:16:3: warning: identifier 'static_assert' is a keyword in C++11 [-Wc++11-compat]
16 | static_assert(min_val == 2, "result must be 2");
| ^~~~~~~~~~~~~
c2.cpp:1:1: error: 'constexpr' does not name a type
1 | constexpr int min(int a, int b)
| ^~~~~~~~~
c2.cpp:1:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c2.cpp:7:1: error: 'constexpr' does not name a type
7 | constexpr int factorial(int n)
| ^~~~~~~~~
c2.cpp:7:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c2.cpp: In function 'int main()':
c2.cpp:15:3: error: 'constexpr' was not declared in this scope
15 | constexpr int min_val = min(2, 3);
| ^~~~~~~~~
c2.cpp:16:17: error: 'min_val' was not declared in this scope
16 | static_assert(min_val == 2, "result must be 2");
| ^~~~~~~
c2.cpp:16:3: error: 'static_assert' was not declared in this scope
16 | static_assert(min_val == 2, "result must be 2");
| ^~~~~~~~~~~~~
c2.cpp:18:12: error: expected ';' before 'int'
18 | constexpr int factorial_val = factorial(5);
| ^~~~
| ;
c2.cpp:19:17: error: 'factorial_val' was not declared in this scope
19 | static_assert(factorial_val == 120, "result muse be 120");
| ^~~~~~~~~~~~~
$ g++ c2.cpp -std=2b -o c2g -I. -Wall
c3.cpp
class Integer {
int value_;
public:
constexpr Integer(int value)
: value_(value) {}
constexpr int get() const
{ return value_; }
};
int main()
{
constexpr Integer x = 3;
static_assert(x.get() == 3, "x value must be 3");
}
コンパイル
$ clang++ c3.cpp -std=03 -o c3l -I. -Wall
c3.cpp:4:3: error: unknown type name 'constexpr'
constexpr Integer(int value)
^
c3.cpp:4:13: error: constructor cannot have a return type
constexpr Integer(int value)
^~~~~~~
c3.cpp:7:3: error: unknown type name 'constexpr'
constexpr int get() const
^
c3.cpp:13:3: error: unknown type name 'constexpr'
constexpr Integer x = 3;
^
c3.cpp:13:20: error: expected ';' at end of declaration
constexpr Integer x = 3;
^
;
c3.cpp:14:17: error: use of undeclared identifier 'x'
static_assert(x.get() == 3, "x value must be 3");
^
6 errors generated.
$ clang++ c3.cpp -std=2b -o c3l -I. -Wall
$ g++ c3.cpp -std=03 -o c3g -I. -Wall
c3.cpp:4:3: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
4 | constexpr Integer(int value)
| ^~~~~~~~~
c3.cpp:14:3: warning: identifier 'static_assert' is a keyword in C++11 [-Wc++11-compat]
14 | static_assert(x.get() == 3, "x value must be 3");
| ^~~~~~~~~~~~~
c3.cpp:4:3: error: 'constexpr' does not name a type
4 | constexpr Integer(int value)
| ^~~~~~~~~
c3.cpp:4:3: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c3.cpp:7:3: error: 'constexpr' does not name a type
7 | constexpr int get() const
| ^~~~~~~~~
c3.cpp:7:3: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
c3.cpp: In function 'int main()':
c3.cpp:13:3: error: 'constexpr' was not declared in this scope
13 | constexpr Integer x = 3;
| ^~~~~~~~~
c3.cpp:14:17: error: 'x' was not declared in this scope
14 | static_assert(x.get() == 3, "x value must be 3");
| ^
c3.cpp:14:3: error: 'static_assert' was not declared in this scope
14 | static_assert(x.get() == 3, "x value must be 3");
| ^~~~~~~~~~~~~
$ g++ c3.cpp -std=2b -o c3g -I. -Wall
参考資料
constexprとconstを正しく使い分ける
C++、constexprのまとめ
constexprおじさん
Back to the C++11 constexpr: すべて大文字である保障のある文字列
constexpr と LUT
C++14 or later で constexpr で std::map 的にリードオンリー連想配列を作るメモ
【ポストコンパイル時定数計算】.NET系言語でconstexprを実現する研究【Mono.Cecil, AssemblyBuilder】
VS2015環境でconstexprな文字列操作
C++でコンパイル時合成数和
constexpr関数の定義の位置による?コンパイルエラーを経験しました
constexprラムダ式に関するコンパイル結果のメモ
constexprラムダ式で包んだconstexpr変数をconstexprではない関数に渡すお話
C++11のconstexprでコンパイル時に文字列のMurMur3ハッシュを計算する
C++ で関数の戻り値が constexpr かどうかを判定する
constexprの読み方
コンパイル時に1のみのビット数を定数化させる関数