mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
learn more c++, it never ends
This commit is contained in:
22
userland/cpp/constexpr_func_infinite_loop.cpp
Normal file
22
userland/cpp/constexpr_func_infinite_loop.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// https://cirosantilli.com/linux-kernel-module-cheat#cpp
|
||||
|
||||
constexpr int f() {
|
||||
int i = 0;
|
||||
while (1)
|
||||
i += 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr int g() {
|
||||
return g();
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
#if 0
|
||||
// GCC 9.2.1. error: ‘constexpr’ loop iteration count exceeds limit of 262144 (use ‘-fconstexpr-loop-limit=’ to increase the limit)
|
||||
static_assert(f() == 0);
|
||||
// GCC 9.2.1. error: ‘constexpr’ evaluation depth exceeds maximum of 512 (use ‘-fconstexpr-depth=’ to increase the maximum)
|
||||
static_assert(g() == 0);
|
||||
#endif
|
||||
}
|
||||
@@ -1,23 +1,30 @@
|
||||
// https://cirosantilli.com/linux-kernel-module-cheat#cpp
|
||||
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
template <class T>
|
||||
template<typename T>
|
||||
struct MyClass {
|
||||
int myFunc() {
|
||||
if constexpr(std::is_integral<T>())
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
MyClass() : myVar{0} {}
|
||||
void modifyIfNotConst() {
|
||||
if constexpr(!isconst) {
|
||||
myVar = 1;
|
||||
}
|
||||
}
|
||||
T myVar;
|
||||
static constexpr bool isconst = std::is_const<T>::value;
|
||||
};
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
#if __cplusplus >= 201703L
|
||||
assert(MyClass<int>().myFunc() == 1);
|
||||
assert(MyClass<float>().myFunc() == 2);
|
||||
MyClass<double> x;
|
||||
MyClass<const double> y;
|
||||
x.modifyIfNotConst();
|
||||
y.modifyIfNotConst();
|
||||
assert(x.myVar == 1);
|
||||
assert(y.myVar == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
199
userland/cpp/initialization_types.cpp
Normal file
199
userland/cpp/initialization_types.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
// https://cirosantilli.com/linux-kernel-module-cheat#cpp-initialization-types
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
// zero-initialization because has static storage
|
||||
// just like a static "local" function variable.
|
||||
int global;
|
||||
|
||||
int main() {
|
||||
|
||||
// First let's list how different initializations are done explicitly in the code.
|
||||
{
|
||||
struct C {
|
||||
int i;
|
||||
constexpr C() : i(0) {}
|
||||
constexpr C(int i) : i(i) {}
|
||||
};
|
||||
|
||||
// Default-initialization.
|
||||
{
|
||||
C i;
|
||||
C *j = new C;
|
||||
}
|
||||
|
||||
// Value initialization.
|
||||
{
|
||||
C i{};
|
||||
C j = C();
|
||||
C k = C{};
|
||||
C *l = new C();
|
||||
C *m = new C{};
|
||||
}
|
||||
|
||||
// Direct initialization.
|
||||
{
|
||||
C i(1);
|
||||
C j{1};
|
||||
C *k = new C(1);
|
||||
}
|
||||
|
||||
// Zero initialization
|
||||
{
|
||||
static C i;
|
||||
}
|
||||
|
||||
// Most vexing parse, function declaration!
|
||||
{
|
||||
C myfunc();
|
||||
}
|
||||
|
||||
// The syntax goes for primitive types. These serve as the basis
|
||||
// for the recursive definition..
|
||||
{
|
||||
// Default.
|
||||
int i;
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/default_initialization
|
||||
// i is POD and is not an array: therefore nothing is done.
|
||||
//assert(i == ?);
|
||||
|
||||
// Value.
|
||||
constexpr int j{};
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/value_initialization
|
||||
// j is not a class type, and is not an array type. Therefore it is zero initialized.
|
||||
static_assert(j == 0);
|
||||
|
||||
// Direct.
|
||||
constexpr int k{1};
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/direct_initialization
|
||||
// is not array, not class, not "if T is a non-class type but the source type is a
|
||||
// class type" whatever that means, and not bool, therefore standard conversion is used
|
||||
// and the value is set.
|
||||
static_assert(k == 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, let's see which implicit initializations are done for each case recursively.
|
||||
{
|
||||
{
|
||||
struct C { int i; };
|
||||
static_assert(std::is_default_constructible<C>());
|
||||
static_assert(std::is_aggregate<C>());
|
||||
|
||||
// Default
|
||||
C a;
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/default_initialization
|
||||
// - non-POD? no
|
||||
// - array? no
|
||||
// - then: nothing is done.
|
||||
//assert(i == ?);
|
||||
|
||||
// Value
|
||||
constexpr C b{};
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/value_initialization
|
||||
// - class type with no default constructor? no
|
||||
// - default constructor that is neither user-provided nor deleted: yes
|
||||
// - zero initialize
|
||||
// - has a non-trivial default constructor
|
||||
// - no
|
||||
assert(b.i == 0);
|
||||
|
||||
// Aggregate
|
||||
constexpr C c{5};
|
||||
static_assert(c.i == 5);
|
||||
|
||||
// Zero
|
||||
static C d;
|
||||
assert(d.i == 0);
|
||||
}
|
||||
|
||||
{
|
||||
struct C {
|
||||
int i;
|
||||
constexpr C() : i(3) {};
|
||||
constexpr C(int i) : i(i) {};
|
||||
};
|
||||
static_assert(!std::is_pod<C>());
|
||||
|
||||
// Default
|
||||
constexpr C a;
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/default_initialization
|
||||
// - non-POD? yes. Therefore: call C(). which initializes i.
|
||||
static_assert(a.i == 3);
|
||||
|
||||
// Value
|
||||
constexpr C b{};
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/value_initialization
|
||||
// - class type with no default constructor? no
|
||||
// - user-provided default constructor? yes. Therefore, default initialize the object.
|
||||
// So we fall on the above case, and the variable does get set.
|
||||
static_assert(b.i == 3);
|
||||
|
||||
// Direct
|
||||
constexpr C c{5};
|
||||
// Following the cases at:
|
||||
// https://en.cppreference.com/w/cpp/language/_initialization
|
||||
// - array type? no
|
||||
// - class type? yes. Call constructor.
|
||||
static_assert(c.i == 5);
|
||||
}
|
||||
|
||||
{
|
||||
struct C {
|
||||
int i;
|
||||
constexpr C(int i) : i(i) {};
|
||||
};
|
||||
static_assert(!std::is_pod<C>());
|
||||
static_assert(!std::is_default_constructible<C>());
|
||||
|
||||
#if 0
|
||||
// Cannot be default initialized if not default constructible.
|
||||
// error: no matching function
|
||||
constexpr C a;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Cannot be value initialized if not default constructible.
|
||||
// error: no matching function
|
||||
C b{};
|
||||
#endif
|
||||
|
||||
// Direct initialize
|
||||
constexpr C c{5};
|
||||
static_assert(!std::is_pod<C>());
|
||||
// - class type with no default constructor? yes
|
||||
}
|
||||
|
||||
//struct A { T t; A() : t() {} };
|
||||
//A a; // t is value-initialized
|
||||
//A a{}; // t is value-initialized
|
||||
|
||||
//struct A { T t; A() : t{} {} };
|
||||
//A a; // t is TODO
|
||||
//A a{}; //
|
||||
|
||||
//struct A { T t; A() {} };
|
||||
//A a; // t is TODO
|
||||
//A a{}; // t is TODO
|
||||
|
||||
//struct A { T t; A() = default };
|
||||
//A d; // t is TOAO
|
||||
//A d{}; // t is TOAO
|
||||
|
||||
//struct A { T t; A() = deleted };
|
||||
//A e; // t is TODO
|
||||
//A e{}; // t is TODO
|
||||
|
||||
//struct A { T t; A(T t) {} };
|
||||
//A f; // t is TODO
|
||||
//A f{}; // t is TODO
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
// https://cirosantilli.com/linux-kernel-module-cheat#cpp
|
||||
|
||||
#include <cassert>
|
||||
|
||||
int main() {
|
||||
|
||||
struct D {
|
||||
int i;
|
||||
D() {}
|
||||
D(int i) : i(i) {}
|
||||
constexpr D() : i(0) {}
|
||||
constexpr D(int i) : i(i) {}
|
||||
};
|
||||
|
||||
struct C {
|
||||
int i;
|
||||
C() : i(1) {}
|
||||
C(int i) : i(i) {}
|
||||
C(const D& d) : i(d.i) {}
|
||||
constexpr C() : i(1) {}
|
||||
constexpr C(int i) : i(i) {}
|
||||
constexpr C(const D& d) : i(d.i) {}
|
||||
};
|
||||
|
||||
// Declares *FUNCTION* called `c` that returns `C` inside function main.
|
||||
@@ -25,7 +23,7 @@ int main() {
|
||||
// Therefore there would be not way for C++ to distinguish between the two,
|
||||
// and still be backwards compatible with C.
|
||||
{
|
||||
C c();
|
||||
constexpr C c();
|
||||
|
||||
#if 0
|
||||
// ERROR: function definition is not possible inside another function.
|
||||
@@ -37,24 +35,24 @@ int main() {
|
||||
|
||||
// If you want to call a default constructor, use:
|
||||
{
|
||||
C c;
|
||||
assert(c.i == 1);
|
||||
constexpr C c;
|
||||
static_assert(c.i == 1);
|
||||
}
|
||||
|
||||
// For non-default constructors, literal arguments disambiguate
|
||||
// things as this syntax could not possibly be a function declaration.
|
||||
{
|
||||
C c(2);
|
||||
assert(c.i == 2);
|
||||
constexpr C c(2);
|
||||
static_assert(c.i == 2);
|
||||
}
|
||||
|
||||
// But sometimes even arguments are not enough: here D()
|
||||
// is interpreted as "a function of type `D f()`"
|
||||
{
|
||||
C c(D(2));
|
||||
constexpr C c(D());
|
||||
#if 0
|
||||
// error: request for member ‘i’ in ‘c’, which is of non-class type ‘main()::C(main()::D (*)())’
|
||||
assert(c.i == 2);
|
||||
static_assert(c.i == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -63,22 +61,22 @@ int main() {
|
||||
{
|
||||
// Extra parenthesis.
|
||||
{
|
||||
C c((D(2)));
|
||||
assert(c.i == 2);
|
||||
constexpr C c((D(2)));
|
||||
static_assert(c.i == 2);
|
||||
}
|
||||
|
||||
// Initialize through assignment. TODO likely guaranteed to be cost-free,
|
||||
// but confirm.
|
||||
{
|
||||
C c = C((D(2)));
|
||||
assert(c.i == 2);
|
||||
constexpr C c = C((D(2)));
|
||||
static_assert(c.i == 2);
|
||||
}
|
||||
|
||||
// Initializer list. Only works if there is no initializer_list constructor.
|
||||
// Only works in general if c does not have an ambiguous initializer_list constructor though.
|
||||
{
|
||||
C c{D(2)};
|
||||
assert(c.i == 2);
|
||||
constexpr C c{D(2)};
|
||||
static_assert(c.i == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user