First commit
[cpp_sandbox.git] / Sandbox / Concepts.cpp
1 #include "Concepts.h"
2
3 #include <iostream>
4 #include <functional>
5 #include <cmath>
6 #include <concepts>
7 #include <type_traits>
8 #include <vector>
9 using namespace std;
10
11 // From: "Demo Zoo: Zero Cost Abstractions in C++20, Rust, & Zig": https://www.youtube.com/watch?v=43X9ia-qpds
12
13 namespace Concepts
14 {
15 template<class Vec>
16 using Scalar = std::decay_t<decltype(Vec()[0])>;
17
18 template<class Vec>
19 concept FloatVec =
20 std::floating_point<Scalar<Vec>> &&
21 requires(Vec vec)
22 {
23 { vec.size() } -> std::integral;
24 };
25
26 template<FloatVec Vec>
27 auto norm(Vec vec) -> Scalar<Vec> // Should be 'norm(const Vec& vec)' but it doesn't work with VS 2019 16.6.3.
28 {
29 using Index = decltype(vec.size());
30 Scalar<Vec> result = 0;
31 for (Index i = 0; i < vec.size(); i += 1)
32 {
33 result += vec[i] * vec[i];
34 }
35 return std::sqrt(result);
36 }
37
38 struct Point2
39 {
40 float x = 0;
41 float y = 0;
42
43 auto size() -> int {
44 return 2;
45 }
46
47 auto operator[](int i) const -> float {
48 return i == 0 ? x : y;
49 }
50 };
51
52 float norm2(float x, float y)
53 {
54 return norm(Point2{ x, y });
55 }
56
57 double norm_nd(const std::vector<double>& a)
58 {
59 return norm(a);
60 }
61 }
62
63 void Concepts::tests()
64 {
65 cout << "norm: " << norm_nd({ 1, 2, 3 }) << endl;
66 cout << "norm: " << norm2(3, 4) << endl;
67 }