Created
August 16, 2020 02:19
-
-
Save crcrpar/0c49633356cf4fc9aaa2d54d74a1294c to your computer and use it in GitHub Desktop.
template things
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ref: https://www.youtube.com/watch?v=VIz6xBvwYd8 | |
#include <stdio.h> | |
#include <type_traits> | |
#include <memory> | |
template <typename Element> | |
struct tree_iterator { | |
tree_iterator& operator ++(); | |
static std::false_type support_plus; | |
// In practice | |
// using support_plus = std::false_type; | |
}; | |
template <class Element> | |
struct vector_iterator { | |
vector_iterator& operator ++(); | |
vector_iterator operator + (int); | |
static std::true_type support_plus; | |
// In practice | |
// using support_plus = std::true_type; | |
}; | |
template <class Element> | |
struct vector { | |
using iterator = vector_iterator<Element>; | |
}; | |
template <class Element> | |
struct set { | |
using iterator = tree_iterator<Element>; | |
}; | |
template <class Iter> | |
Iter advance(Iter begin, int n) { | |
for (int i = 0; i < n; ++i) { | |
++begin; | |
} | |
return begin; | |
} | |
template <class E> | |
vector_iterator<E> advance(vector_iterator<E> begin, int n) { | |
return begin + n; | |
} | |
template <class It> | |
It advance_impl(It begin, int n, std::false_type /* sp */) { | |
for (int i = 0; i < n; ++i) { | |
++begin; | |
} | |
return begin; | |
} | |
template <class It> | |
It advance_impl(It begin, int n, std::true_type /* sp */) { | |
return begin + n; | |
} | |
template <class Iter> | |
auto advance(Iter begin, int n) { | |
return advance_impl(begin, n, Iter::supports_plus); | |
// In practice | |
// return advcnce_impl(begin, n, typename Iter::support_plus{}); | |
// Create an object of that type | |
} | |
// `template` things | |
struct S1 { static constexpr int A = 0; }; | |
template <class T> | |
void fooS1(int x) { | |
T::A<0>(x); | |
} | |
struct S2 { template<int N> static void A(int) {} }; | |
template <class T> | |
void fooS2(int x) { | |
T::template A<0>(x); | |
} | |
struct S3 { template<int N> struct A{}; }; | |
template <class T> | |
void fooS3(int x) { | |
typename T::template A <0> (X); | |
} | |
template <class /*Iter*/> | |
struct iter_traits { | |
using support_plus = std::false_type; | |
}; | |
template <class T> | |
struct iter_traits<T *> { | |
using support_plus = std::true_type; | |
}; | |
template <class T> | |
struct iter_traits<vector_iterator<T>> { | |
using support_plus = std::true_type; | |
}; | |
// Now the advance function becomes... | |
#if 0 | |
template <class Iter> | |
auto advance (Iter begin, int n) { | |
return advance_impl( | |
begin, n, | |
typename iter_traits<Iter>::supports_plus{} | |
); | |
} | |
#endif | |
// STL best practice: _t synonyms | |
template <class Iter> | |
using iter_supports_plus_t = | |
typename iter_traits<Iter>::supports_plus; | |
template <class Iter> | |
auto advance2(Iter begin, int n) { | |
return advance_impl( | |
begin, n, | |
iter_supports_plus_t<Iter>{} | |
); | |
} | |
template <class T> | |
int a() { return 1; } | |
template int a<int>(); | |
template <class T> | |
void g() { | |
static_assert(sizeof(T) == 4); | |
} | |
void stub_g() { | |
g<int>(); | |
} | |
template <class T> int ff1(); | |
template <class T> int ff2() { static_assert(sizeof(T) == 2); } | |
template <class T> int ff3() { static_assert(sizeof(T) == 2); } | |
// extern template int ff3<int>(); | |
template <> int ff3<int>() { return 1; } | |
int ff1_a = ff1<int>(); | |
// int ff2_a = ff2<int>(); | |
int ff3_a = ff3<int>(); // as ff3<int> has an explicit instantiation | |
template <typename T> int vt; | |
int vt_i = vt<int>; | |
// variadic templates | |
using Cat = unsigned long long; | |
template <class T, class... Args> | |
void mcdonald(void *where, Args&&... args) { | |
new (where) T(std::forward<Args>(args)...); | |
} | |
void populate(void *here, void *there, int meow) { | |
mcdonald<Cat>(here, meow); | |
// Why the below doesn't compile? | |
// mcdonald<Cat>(there, meow, meow); | |
} | |
// Type deduction in a nutshell, v2 | |
template <class T, class... Us> | |
void variadic_f(Us... us) { puts(__PRETTY_FUNCTION__); } // MSVC: __FUNCSIG__ | |
void stub_variadic_f() { | |
variadic_f<char>(0, 1, 2); // [T=char, Us=<int, int, int>] | |
variadic_f<char, char>(0, 1, 2); // [T=char, Us=<char, int, int>] | |
} | |
template <class T, class... Us, class V> void f_v2(); | |
// auto stub_f_v2 = []() { | |
// f_v2<int, char, int>(); // T=int, Us=<char, int>, V can't be deduced. | |
// }; | |
template <class... Ts, class U> void g_v2(U); | |
auto stub_g_v2 = []() { | |
g_v2<int, char>(3.1); // Ts=<int, char>, U=double | |
}; | |
template <class... Ts> void h_v2(Ts...); | |
auto stub_h_v2 = []() { | |
h_v2<int, char>(0, 0, 3.1); // Ts=<int, char, double> | |
}; | |
template <class... Ts, class U> void f_v2_1(U, Ts...); | |
auto stub_f_v2_1 = []() { | |
f_v2_1('x', 1, 2); // U=char, Ts=<int,int> | |
}; | |
template <class T, class... Us> void g_v2_1(Us... us, T); | |
// auto stub_g_v2_1 = []() { | |
// g_v2_1('x', 1, 2); // us doesn't contribute to deduction, fails! | |
// }; | |
template <class T, class... Us> void h_v2_1(Us... us, T); | |
auto stub_h_v2_1 = []() { | |
h_v2_1<int, int, int>('x', 1, 2); | |
}; | |
/** | |
* Two patterns to know: | |
* The CRTO | |
* The Mixin Pattern | |
*/ | |
// CRTP | |
struct Cat1 { | |
void speak() { puts("mewo"); } | |
void speaktwice() { speak(); speak(); } | |
}; | |
struct Dog1 { | |
void speak() { puts("woof"); } | |
void speaktwice() { speak(); speak(); } | |
}; | |
// template <auto> | |
template <class Ty, Ty Value> | |
struct integral_constant { | |
static constexpr auto value = Value; | |
}; | |
using fortytwo_type = integral_constant<int, 42>; | |
using true_type = integral_constant<bool, true>; | |
// C++17 | |
template <auto Value> | |
struct new_integral_constant { | |
static constexpr auto value = Value; | |
}; | |
using fortytwo_type_17 = new_integral_constant<42>; | |
using true_type_17 = new_integral_constant<true>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment