├── typelist ├── typelist.hpp ├── cttypelist.hpp ├── ctvalue.hpp ├── ctvalue17.hpp ├── identity.hpp ├── cons.hpp ├── addconst.hpp ├── consfront.hpp ├── conspopfront.hpp ├── consisempty.hpp ├── typelistpopback.hpp ├── variadictransform.hpp ├── typelistisempty.hpp ├── conspushfront.hpp ├── typelistfront.hpp ├── typelistpopfront.hpp ├── multiply.hpp ├── nthelement.hpp ├── largesttypeacc0.hpp ├── select.hpp ├── insertionsorttest.hpp ├── typelistpushback.hpp ├── typelistpushfront.hpp ├── conslisttest.hpp ├── typelistreverse.hpp ├── valuelisttest.hpp ├── largesttype.hpp ├── largesttypeacc.hpp ├── genericlargesttype.hpp ├── accumulate.hpp ├── transform.hpp ├── insertionsort.hpp ├── valuelist.hpp ├── genericpushback.hpp └── insertsorted.hpp ├── basics ├── addvalue.hpp ├── byvalue.hpp ├── maxauto.hpp ├── byref.hpp ├── maxconstexpr.hpp ├── max1.hpp ├── maxdecltype.hpp ├── maxcommon.hpp ├── myfirst.hpp ├── maxdefault3.hpp ├── myfirstmain.cpp ├── maxdecltypedecay.hpp ├── boolstringgetbool.hpp ├── maxdefault1.hpp ├── maxdefault4.hpp ├── lessarray.hpp ├── lessstring.hpp ├── myfirst.cpp ├── isprime14.hpp ├── boolstring.hpp ├── maxdefaultdeclval.hpp ├── len1.hpp ├── varprint1.hpp ├── foreach.hpp ├── errornovel1.cpp ├── invoke.hpp ├── varprint2.hpp ├── len2.hpp ├── stack6assign.hpp ├── specialmemtmpl3.cpp ├── stack5assign.hpp ├── myfirst2.hpp ├── printcoll.hpp ├── max1.cpp ├── stack7assign.hpp ├── stack8decl.hpp ├── tmplparamref.cpp ├── stack1test.cpp ├── addspace.hpp ├── cref.cpp ├── message.cpp ├── foreachinvoke.hpp ├── stack5decl.hpp ├── referror1.cpp ├── isprime11.hpp ├── stack3test.cpp ├── stack6decl.hpp ├── stacknontype.cpp ├── max2.cpp ├── specialmemtmpl2.hpp ├── errornovel2.cpp ├── max4.cpp ├── stack7decl.hpp ├── stackauto.cpp ├── invokeret.hpp ├── foldtraverse.cpp ├── max3ref.cpp ├── referror2.cpp ├── specialmemtmpl3.hpp ├── move2.cpp ├── stack1.hpp ├── stack2.hpp ├── max3val.cpp ├── stack3.hpp ├── isprime.hpp ├── stackpartspec.hpp ├── stack9test.cpp ├── move1.cpp ├── foreachinvoke.cpp ├── varusing.cpp ├── specialmemtmpl1.cpp ├── foreach.cpp ├── stackdeduce1.hpp ├── arrays.hpp ├── arrays.cpp ├── stacknontype.hpp └── stackauto.hpp ├── tuples ├── ctvalue.hpp ├── popfront.hpp ├── maketuple.hpp ├── popback.hpp ├── copycounter.hpp ├── select.hpp ├── pushfront.hpp ├── reverse.hpp ├── tupleelt1.hpp ├── indexsort.cpp ├── indexlistreverse.hpp ├── compressedtuple1.cpp ├── constantget.hpp ├── tuplestorage1.hpp ├── makeindexlist.hpp ├── tuplesorttest.hpp ├── pushback.hpp ├── apply.hpp ├── tupleeq.hpp ├── copycountertest.hpp ├── tupleio.hpp ├── tupleget.hpp ├── tuple0.hpp ├── tuplestorage3.hpp ├── tupleelt2.hpp ├── tuplesort.hpp ├── splat.hpp ├── tupletypelist.hpp └── tuplestorage2.hpp ├── variant ├── variantdefaultctor.hpp ├── variantempty.hpp ├── variantstorageastuple.hpp ├── variantis.hpp ├── variantcopyctor.hpp ├── variantmovector.hpp ├── variantvisitresultstd.hpp ├── variantcopyctortmpl.hpp ├── visit.cpp ├── commontype.hpp ├── variantcopyassign.hpp ├── variantstorageasunion.hpp ├── variantdestroy17.hpp ├── variantdestroy.hpp ├── variantchoicedestroy.hpp ├── variantget.hpp ├── variantvisitresult.hpp ├── variantdefaultctor.cpp ├── variant.cpp ├── printrec.cpp ├── findindexof.hpp ├── variantvisitimpl.hpp ├── variantpromote.cpp ├── variantchoiceinit.hpp ├── variantvisitresultcommon.hpp ├── accumulate.hpp ├── variantstorage.hpp ├── variantexception.cpp ├── variantchoice.hpp ├── variantvisit.hpp └── variantchoiceassign.hpp ├── bridge ├── forupto2.hpp ├── forupto3.hpp ├── functorbridge.hpp ├── tryequals.hpp ├── forupto1.cpp ├── specificfunctorbridge.hpp ├── forupto4.cpp └── isequalitycomparable.hpp ├── details ├── funcoverload1.hpp ├── funcoverload1.cpp ├── implicit.cpp ├── lazy2.cpp ├── fppm.cpp ├── nontmpl1.cpp ├── inject.cpp ├── funcoverload2.cpp ├── nontmpl2.cpp ├── max.cpp ├── adl.cpp ├── variadicoverload.cpp ├── definitions2.hpp ├── tupleoverload.cpp ├── definitions1.hpp ├── tmplconstr.cpp ├── lazy1.hpp └── definitions3.hpp ├── traits ├── accumtraits4bigint.hpp ├── issame.hpp ├── plus1.hpp ├── boolconstant.hpp ├── issame0.hpp ├── isnothrowmoveconstructible1.hpp ├── removecv.hpp ├── sumpolicy2.hpp ├── sizeof.cpp ├── removeconst.hpp ├── plus2.hpp ├── sumpolicy1.hpp ├── isenum.hpp ├── removereference.hpp ├── removevolatile.hpp ├── isreference.hpp ├── islvaluereference.hpp ├── isrvaluereference.hpp ├── accum1.hpp ├── isclass.hpp ├── ispointer.hpp ├── ispointertomember.hpp ├── isfundatest.cpp ├── accum5.hpp ├── rparam1.cpp ├── plus3.hpp ├── addreference.hpp ├── accum0.hpp ├── hasbegin.hpp ├── elementtype.cpp ├── accumtraits3.hpp ├── hassizetype.hpp ├── accum2.hpp ├── rparam.hpp ├── hastype.hpp ├── accum3.hpp ├── hasless.hpp ├── hasmember.hpp ├── hasplus.hpp ├── accum6.hpp ├── isdefaultconstructible1.hpp ├── accum6.cpp ├── hasmember.cpp ├── hasvarious.hpp ├── isdefaultconstructible3.hpp ├── accum7.hpp ├── accumtraits2.hpp ├── decay.hpp ├── isarray.hpp ├── rparamcls.hpp ├── isnothrowmoveconstructible2.hpp ├── isdefaultconstructible2.hpp ├── issame.cpp ├── hastype.cpp ├── rparam2.cpp ├── accum1.cpp ├── isfunction.hpp ├── decay.cpp ├── passbyvalue.cpp ├── elementtype.hpp ├── ifthenelse.hpp ├── smallestint.hpp ├── accumtraits4.hpp ├── isconvertible.hpp ├── isfunda.hpp ├── isvalid.hpp ├── isvalid1.cpp └── isvalid2.cpp ├── inherit ├── empty.cpp ├── listnode.hpp ├── person.hpp ├── countertest.cpp ├── projectioniterator.cpp ├── wrapper.cpp ├── ebco1.cpp ├── ebco2.cpp ├── equalitycomparable.cpp ├── listnodeiterator0.hpp ├── objectcounter.hpp ├── basememberpair.hpp ├── virtual.cpp ├── iteratorfacadeaccessskel.hpp └── projectioniteratorskel.hpp ├── exprtmpl ├── sarray1.cpp ├── exprops4.hpp ├── sarray2.cpp ├── exprscalar.hpp ├── exprops1a.hpp ├── exprops3.hpp ├── sarrayops2.hpp ├── sarrayops1.hpp ├── exprops2.hpp ├── sarray1.hpp └── exprarray.hpp ├── poly ├── conceptsreq.hpp ├── MyClass.hpp ├── coord.hpp ├── statichier.hpp ├── printmax.cpp ├── conceptspoly.hpp ├── dynahier.hpp ├── dynapoly.cpp └── staticpoly.cpp ├── meta ├── ratio.hpp ├── pow3enum.hpp ├── pow3const.hpp ├── sqrt1.cpp ├── duration.hpp ├── ratioadd.hpp ├── sqrt1.hpp ├── removeallextents.hpp ├── sqrt2.hpp ├── ifthenelse.hpp ├── durationadd.hpp ├── sqrtconstexpr.hpp └── unruh.cpp ├── typeoverload ├── enableif.hpp ├── min2.hpp ├── min3.hpp ├── min.hpp ├── iscontextualbool.hpp ├── container4.hpp ├── isconvertible.hpp ├── container1.hpp ├── advance3.hpp ├── lessresult.hpp ├── advance2.hpp └── min.cpp ├── deduce ├── initlist.cpp ├── resulttypetmpl.cpp └── aliastemplate.cpp ├── overload ├── initlistovl.cpp ├── initlistctor.cpp └── initlist.cpp ├── names └── anglebrackethack.cpp ├── debugging ├── hasderef.hpp └── tracertest.cpp ├── utils ├── traits1.cpp ├── isconstructible.cpp └── traits2.cpp └── README.md /typelist/typelist.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Typelist {}; 3 | -------------------------------------------------------------------------------- /basics/addvalue.hpp: -------------------------------------------------------------------------------- 1 | template 2 | T addValue(T x) { 3 | return x + Val; 4 | } 5 | -------------------------------------------------------------------------------- /basics/byvalue.hpp: -------------------------------------------------------------------------------- 1 | template 2 | T checked(T a, T b) { 3 | return test() ? a : b; 4 | } 5 | -------------------------------------------------------------------------------- /typelist/cttypelist.hpp: -------------------------------------------------------------------------------- 1 | template 2 | using CTTypelist = Typelist...>; 3 | -------------------------------------------------------------------------------- /basics/maxauto.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto max(T1 a, T2 b) { 3 | return b < a ? a : b; 4 | } 5 | -------------------------------------------------------------------------------- /tuples/ctvalue.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct CTValue { 3 | static constexpr T value = Value; 4 | }; 5 | -------------------------------------------------------------------------------- /typelist/ctvalue.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct CTValue { 3 | static constexpr T value = Value; 4 | }; 5 | -------------------------------------------------------------------------------- /typelist/ctvalue17.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct CTValue { 3 | static constexpr auto value = Value; 4 | }; 5 | -------------------------------------------------------------------------------- /basics/byref.hpp: -------------------------------------------------------------------------------- 1 | template 2 | T const& checked(T const& a, T const& b) { 3 | return test() ? a : b; 4 | } 5 | -------------------------------------------------------------------------------- /basics/maxconstexpr.hpp: -------------------------------------------------------------------------------- 1 | template 2 | constexpr auto max(T1 a, T2 b) { 3 | return b < a ? a : b; 4 | } 5 | -------------------------------------------------------------------------------- /typelist/identity.hpp: -------------------------------------------------------------------------------- 1 | // yield T when using member Type: 2 | template 3 | struct IdentityT { 4 | using Type = T; 5 | }; 6 | -------------------------------------------------------------------------------- /basics/max1.hpp: -------------------------------------------------------------------------------- 1 | template 2 | T max(T a, T b) { 3 | // if b < a then yield a else yield b 4 | return b < a ? a : b; 5 | } 6 | -------------------------------------------------------------------------------- /variant/variantdefaultctor.hpp: -------------------------------------------------------------------------------- 1 | template 2 | Variant::Variant() { 3 | *this = Front>(); 4 | } 5 | -------------------------------------------------------------------------------- /basics/maxdecltype.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto max(T1 a, T2 b) -> decltype(b < a ? a : b) { 3 | return b < a ? a : b; 4 | } 5 | -------------------------------------------------------------------------------- /variant/variantempty.hpp: -------------------------------------------------------------------------------- 1 | template 2 | bool Variant::empty() const { 3 | return this->getDiscriminator() == 0; 4 | } 5 | -------------------------------------------------------------------------------- /bridge/forupto2.hpp: -------------------------------------------------------------------------------- 1 | void forUpTo(int n, void (*f)(int)) { 2 | for (int i = 0; i != n; ++i) { 3 | f(i); // call passed function f for i 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tuples/popfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | PopFront> popFront(Tuple const& tuple) { 3 | return tuple.getTail(); 4 | } 5 | -------------------------------------------------------------------------------- /details/funcoverload1.hpp: -------------------------------------------------------------------------------- 1 | template 2 | int f(T) { 3 | return 1; 4 | } 5 | 6 | template 7 | int f(T*) { 8 | return 2; 9 | } 10 | -------------------------------------------------------------------------------- /traits/accumtraits4bigint.hpp: -------------------------------------------------------------------------------- 1 | template <> 2 | struct AccumulationTraits { 3 | using AccT = BigInt; 4 | static BigInt zero() { return BigInt{0}; } 5 | }; 6 | -------------------------------------------------------------------------------- /inherit/empty.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class EmptyClass {}; 4 | 5 | int main() { 6 | std::cout << "sizeof(EmptyClass): " << sizeof(EmptyClass) << '\n'; 7 | } 8 | -------------------------------------------------------------------------------- /inherit/listnode.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class ListNode { 3 | public: 4 | T value; 5 | ListNode* next = nullptr; 6 | ~ListNode() { delete next; } 7 | }; 8 | -------------------------------------------------------------------------------- /tuples/maketuple.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto makeTuple(Types&&... elems) { 3 | return Tuple...>(std::forward(elems)...); 4 | } 5 | -------------------------------------------------------------------------------- /variant/variantstorageastuple.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Variant { 3 | public: 4 | Tuple storage; 5 | unsigned char discriminator; 6 | }; 7 | -------------------------------------------------------------------------------- /basics/maxcommon.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | std::common_type_t max(T1 a, T2 b) { 5 | return b < a ? a : b; 6 | } 7 | -------------------------------------------------------------------------------- /tuples/popback.hpp: -------------------------------------------------------------------------------- 1 | template 2 | PopBack> popBack(Tuple const& tuple) { 3 | return reverse(popFront(reverse(tuple))); 4 | } 5 | -------------------------------------------------------------------------------- /exprtmpl/sarray1.cpp: -------------------------------------------------------------------------------- 1 | #include "sarray1.hpp" 2 | #include "sarrayops1.hpp" 3 | 4 | int main() { 5 | SArray x(1000), y(1000); 6 | //... 7 | x = 1.2 * x + x * y; 8 | } 9 | -------------------------------------------------------------------------------- /typelist/cons.hpp: -------------------------------------------------------------------------------- 1 | class Nil {}; 2 | 3 | template 4 | class Cons { 5 | public: 6 | using Head = HeadT; 7 | using Tail = TailT; 8 | }; 9 | -------------------------------------------------------------------------------- /typelist/addconst.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct AddConstT { 3 | using Type = T const; 4 | }; 5 | 6 | template 7 | using AddConst = typename AddConstT::Type; 8 | -------------------------------------------------------------------------------- /basics/myfirst.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MYFIRST_HPP 2 | #define MYFIRST_HPP 3 | 4 | // declaration of template 5 | template 6 | void printTypeof(T const&); 7 | 8 | #endif // MYFIRST_HPP 9 | -------------------------------------------------------------------------------- /basics/maxdefault3.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template > 4 | RT max(T1 a, T2 b) { 5 | return b < a ? a : b; 6 | } 7 | -------------------------------------------------------------------------------- /basics/myfirstmain.cpp: -------------------------------------------------------------------------------- 1 | #include "myfirst.hpp" 2 | 3 | // use of the template 4 | int main() { 5 | double ice = 3.0; 6 | printTypeof(ice); // call function template for type double 7 | } 8 | -------------------------------------------------------------------------------- /tuples/copycounter.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct CopyCounter { 3 | inline static unsigned numCopies = 0; 4 | CopyCounter() {} 5 | CopyCounter(CopyCounter const&) { ++numCopies; } 6 | }; 7 | -------------------------------------------------------------------------------- /bridge/forupto3.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void forUpTo(int n, std::function f) { 4 | for (int i = 0; i != n; ++i) { 5 | f(i); // call passed function f for i 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /traits/issame.hpp: -------------------------------------------------------------------------------- 1 | #include "boolconstant.hpp" 2 | 3 | template 4 | struct IsSameT : FalseType {}; 5 | 6 | template 7 | struct IsSameT : TrueType {}; 8 | -------------------------------------------------------------------------------- /tuples/select.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto select(Tuple const& t, Valuelist) { 3 | return makeTuple(get(t)...); 4 | } 5 | -------------------------------------------------------------------------------- /basics/maxdecltypedecay.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | auto max(T1 a, T2 b) -> typename std::decay::type { 5 | return b < a ? a : b; 6 | } 7 | -------------------------------------------------------------------------------- /typelist/consfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class FrontT { 3 | public: 4 | using Type = typename List::Head; 5 | }; 6 | 7 | template 8 | using Front = typename FrontT::Type; 9 | -------------------------------------------------------------------------------- /variant/variantis.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | bool Variant::is() const { 4 | return this->getDiscriminator() == VariantChoice::Discriminator; 5 | } 6 | -------------------------------------------------------------------------------- /poly/conceptsreq.hpp: -------------------------------------------------------------------------------- 1 | #include "coord.hpp" 2 | 3 | template 4 | concept GeoObj = requires(T x) { 5 | { x.draw() } 6 | ->void; 7 | { x.center_of_gravity() } 8 | ->Coord; 9 | //... 10 | }; 11 | -------------------------------------------------------------------------------- /typelist/conspopfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PopFrontT { 3 | public: 4 | using Type = typename List::Tail; 5 | }; 6 | 7 | template 8 | using PopFront = typename PopFrontT::Type; 9 | -------------------------------------------------------------------------------- /basics/boolstringgetbool.hpp: -------------------------------------------------------------------------------- 1 | // full specialization for BoolString::getValue<>() for bool 2 | template <> 3 | inline bool BoolString::get() const { 4 | return value == "true" || value == "1" || value == "on"; 5 | } 6 | -------------------------------------------------------------------------------- /basics/maxdefault1.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template > 5 | RT max(T1 a, T2 b) { 6 | return b < a ? a : b; 7 | } 8 | -------------------------------------------------------------------------------- /variant/variantcopyctor.hpp: -------------------------------------------------------------------------------- 1 | template 2 | Variant::Variant(Variant const& source) { 3 | if (!source.empty()) { 4 | source.visit([&](auto const& value) { *this = value; }); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /details/funcoverload1.cpp: -------------------------------------------------------------------------------- 1 | #include "funcoverload1.hpp" 2 | #include 3 | 4 | int main() { 5 | std::cout << f((int*)nullptr); // calls f(T) 6 | std::cout << f((int*)nullptr); // calls f(T*) 7 | } 8 | -------------------------------------------------------------------------------- /meta/ratio.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct Ratio { 3 | static constexpr unsigned num = N; // numerator 4 | static constexpr unsigned den = D; // denominator 5 | using Type = Ratio; 6 | }; 7 | -------------------------------------------------------------------------------- /typelist/consisempty.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsEmpty { 3 | static constexpr bool value = false; 4 | }; 5 | 6 | template <> 7 | struct IsEmpty { 8 | static constexpr bool value = true; 9 | }; 10 | -------------------------------------------------------------------------------- /details/implicit.cpp: -------------------------------------------------------------------------------- 1 | template 2 | DstT implicit_cast(SrcT const& x) // SrcT can be deduced, but DstT cannot 3 | { 4 | return x; 5 | } 6 | 7 | int main() { double value = implicit_cast(-1); } 8 | -------------------------------------------------------------------------------- /traits/plus1.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct PlusResultT { 3 | using Type = decltype(T1() + T2()); 4 | }; 5 | 6 | template 7 | using PlusResult = typename PlusResultT::Type; 8 | -------------------------------------------------------------------------------- /typelist/typelistpopback.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PopBackT { 3 | public: 4 | using Type = Reverse>>; 5 | }; 6 | 7 | template 8 | using PopBack = typename PopBackT::Type; 9 | -------------------------------------------------------------------------------- /variant/variantmovector.hpp: -------------------------------------------------------------------------------- 1 | template 2 | Variant::Variant(Variant&& source) { 3 | if (!source.empty()) { 4 | std::move(source).visit([&](auto&& value) { *this = std::move(value); }); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /traits/boolconstant.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct BoolConstant { 3 | using Type = BoolConstant; 4 | static constexpr bool value = val; 5 | }; 6 | using TrueType = BoolConstant; 7 | using FalseType = BoolConstant; 8 | -------------------------------------------------------------------------------- /bridge/functorbridge.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class FunctorBridge { 3 | public: 4 | virtual ~FunctorBridge() {} 5 | virtual FunctorBridge* clone() const = 0; 6 | virtual R invoke(Args... args) const = 0; 7 | }; 8 | -------------------------------------------------------------------------------- /details/lazy2.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class VirtualClass { 3 | public: 4 | virtual ~VirtualClass() {} 5 | virtual T vmem(); // Likely ERROR if instantiated without definition 6 | }; 7 | 8 | int main() { VirtualClass inst; } 9 | -------------------------------------------------------------------------------- /traits/issame0.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsSameT { 3 | static constexpr bool value = false; 4 | }; 5 | 6 | template 7 | struct IsSameT { 8 | static constexpr bool value = true; 9 | }; 10 | -------------------------------------------------------------------------------- /basics/maxdefault4.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto max(T1 a, T2 b) { 3 | return b < a ? a : b; 4 | } 5 | 6 | template 7 | RT max(T1 a, T2 b) { 8 | return b < a ? a : b; 9 | } 10 | -------------------------------------------------------------------------------- /inherit/person.hpp: -------------------------------------------------------------------------------- 1 | struct Person { 2 | std::string firstName; 3 | std::string lastName; 4 | 5 | friend std::ostream& operator<<(std::ostream& strm, Person const& p) { 6 | return strm << p.lastName << ", " << p.firstName; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /typelist/variadictransform.hpp: -------------------------------------------------------------------------------- 1 | template class MetaFun> 2 | class TransformT, MetaFun, false> { 3 | public: 4 | using Type = Typelist::Type...>; 5 | }; 6 | -------------------------------------------------------------------------------- /basics/lessarray.hpp: -------------------------------------------------------------------------------- 1 | template 2 | bool less(T (&a)[N], T (&b)[M]) { 3 | for (int i = 0; i < N && i < M; ++i) { 4 | if (a[i] < b[i]) return true; 5 | if (b[i] < a[i]) return false; 6 | } 7 | return N < M; 8 | } 9 | -------------------------------------------------------------------------------- /basics/lessstring.hpp: -------------------------------------------------------------------------------- 1 | template 2 | bool less(char const (&a)[N], char const (&b)[M]) { 3 | for (int i = 0; i < N && i < M; ++i) { 4 | if (a[i] < b[i]) return true; 5 | if (b[i] < a[i]) return false; 6 | } 7 | return N < M; 8 | } 9 | -------------------------------------------------------------------------------- /basics/myfirst.cpp: -------------------------------------------------------------------------------- 1 | #include "myfirst.hpp" 2 | #include 3 | #include 4 | 5 | // implementation/definition of template 6 | template 7 | void printTypeof(T const& x) { 8 | std::cout << typeid(x).name() << '\n'; 9 | } 10 | -------------------------------------------------------------------------------- /traits/isnothrowmoveconstructible1.hpp: -------------------------------------------------------------------------------- 1 | #include // for bool_constant 2 | #include // for declval 3 | 4 | template 5 | struct IsNothrowMoveConstructibleT 6 | : std::bool_constant()))> {}; 7 | -------------------------------------------------------------------------------- /tuples/pushfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | PushFront, V> pushFront(Tuple const& tuple, 3 | V const& value) { 4 | return PushFront, V>(value, tuple); 5 | } 6 | -------------------------------------------------------------------------------- /typelist/typelistisempty.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class IsEmpty { 3 | public: 4 | static constexpr bool value = false; 5 | }; 6 | 7 | template <> 8 | class IsEmpty> { 9 | public: 10 | static constexpr bool value = true; 11 | }; 12 | -------------------------------------------------------------------------------- /variant/variantvisitresultstd.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class VisitResultT { 3 | public: 4 | using Type = std::common_type_t...>; 5 | }; 6 | -------------------------------------------------------------------------------- /traits/removecv.hpp: -------------------------------------------------------------------------------- 1 | #include "removeconst.hpp" 2 | #include "removevolatile.hpp" 3 | 4 | template 5 | struct RemoveCVT : RemoveConstT::Type> {}; 6 | 7 | template 8 | using RemoveCV = typename RemoveCVT::Type; 9 | -------------------------------------------------------------------------------- /typelist/conspushfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PushFrontT { 3 | public: 4 | using Type = Cons; 5 | }; 6 | 7 | template 8 | using PushFront = typename PushFrontT::Type; 9 | -------------------------------------------------------------------------------- /details/fppm.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class X { 3 | public: 4 | using I = int; 5 | void f(int) {} 6 | }; 7 | 8 | template 9 | void fppm(void (X::*p)(typename X::I)); 10 | 11 | int main() { 12 | fppm(&X<33>::f); // fine: N deduced to be 33 13 | } 14 | -------------------------------------------------------------------------------- /exprtmpl/exprops4.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | Array> Array::operator[]( 4 | Array const& b) { 5 | return Array>(A_Subscript(*this, b)); 6 | } 7 | -------------------------------------------------------------------------------- /traits/sumpolicy2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SUMPOLICY_HPP 2 | #define SUMPOLICY_HPP 3 | 4 | template 5 | class SumPolicy { 6 | public: 7 | static void accumulate(T1& total, T2 const& value) { total += value; } 8 | }; 9 | 10 | #endif // SUMPOLICY_HPP 11 | -------------------------------------------------------------------------------- /variant/variantcopyctortmpl.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | Variant::Variant(Variant const& source) { 4 | if (!source.empty()) { 5 | source.visit([&](auto const& value) { *this = value; }); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /basics/isprime14.hpp: -------------------------------------------------------------------------------- 1 | constexpr bool isPrime(unsigned int p) { 2 | for (unsigned int d = 2; d <= p / 2; ++d) { 3 | if (p % d == 0) { 4 | return false; // found divisor without remainder 5 | } 6 | } 7 | return p > 1; // no divisor without remainder found 8 | } 9 | -------------------------------------------------------------------------------- /meta/pow3enum.hpp: -------------------------------------------------------------------------------- 1 | // primary template to compute 3 to the Nth 2 | template 3 | struct Pow3 { 4 | enum { value = 3 * Pow3::value }; 5 | }; 6 | 7 | // full specialization to end the recursion 8 | template <> 9 | struct Pow3<0> { 10 | enum { value = 1 }; 11 | }; 12 | -------------------------------------------------------------------------------- /traits/sizeof.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct TypeSize { 6 | static std::size_t const value = sizeof(T); 7 | }; 8 | 9 | int main() { 10 | std::cout << "TypeSize::value = " << TypeSize::value << '\n'; 11 | } 12 | -------------------------------------------------------------------------------- /basics/boolstring.hpp: -------------------------------------------------------------------------------- 1 | class BoolString { 2 | private: 3 | std::string value; 4 | 5 | public: 6 | BoolString(std::string const& s) : value(s) {} 7 | template 8 | T get() const { // get value (converted to T) 9 | return value; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /traits/removeconst.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct RemoveConstT { 3 | using Type = T; 4 | }; 5 | 6 | template 7 | struct RemoveConstT { 8 | using Type = T; 9 | }; 10 | 11 | template 12 | using RemoveConst = typename RemoveConstT::Type; 13 | -------------------------------------------------------------------------------- /typeoverload/enableif.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct EnableIfT {}; 3 | 4 | template 5 | struct EnableIfT { 6 | using Type = T; 7 | }; 8 | 9 | template 10 | using EnableIf = typename EnableIfT::Type; 11 | -------------------------------------------------------------------------------- /traits/plus2.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct PlusResultT { 5 | using Type = decltype(std::declval() + std::declval()); 6 | }; 7 | 8 | template 9 | using PlusResult = typename PlusResultT::Type; 10 | -------------------------------------------------------------------------------- /traits/sumpolicy1.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SUMPOLICY_HPP 2 | #define SUMPOLICY_HPP 3 | 4 | class SumPolicy { 5 | public: 6 | template 7 | static void accumulate(T1& total, T2 const& value) { 8 | total += value; 9 | } 10 | }; 11 | 12 | #endif // SUMPOLICY_HPP 13 | -------------------------------------------------------------------------------- /tuples/reverse.hpp: -------------------------------------------------------------------------------- 1 | // basis case 2 | Tuple<> reverse(Tuple<> const& t) { return t; } 3 | 4 | // recursive case 5 | template 6 | Reverse> reverse(Tuple const& t) { 7 | return pushBack(reverse(t.getTail()), t.getHead()); 8 | } 9 | -------------------------------------------------------------------------------- /variant/visit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "variant.hpp" 4 | 5 | int main() { 6 | Variant v(1.5); 7 | auto result = v.visit([](auto const& value) { return value + 1; }); 8 | std::cout << typeid(result).name() << '\n'; 9 | } 10 | -------------------------------------------------------------------------------- /deduce/initlist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | void f(std::initializer_list); 5 | 6 | int main() { 7 | f({2, 3, 5, 7, 9}); // OK: T is deduced to int 8 | f({'a', 'e', 'i', 'o', 'u', 42}); // ERROR: T deduced to both char and int 9 | } 10 | -------------------------------------------------------------------------------- /typelist/typelistfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class FrontT; 3 | 4 | template 5 | class FrontT> { 6 | public: 7 | using Type = Head; 8 | }; 9 | 10 | template 11 | using Front = typename FrontT::Type; 12 | -------------------------------------------------------------------------------- /basics/maxdefaultdeclval.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template () 5 | : std::declval())>> 6 | RT max(T1 a, T2 b) { 7 | return b < a ? a : b; 8 | } 9 | -------------------------------------------------------------------------------- /exprtmpl/sarray2.cpp: -------------------------------------------------------------------------------- 1 | #include "sarray2.hpp" 2 | #include "sarrayops1.hpp" 3 | #include "sarrayops2.hpp" 4 | 5 | int main() { 6 | SArray x(1000), y(1000); 7 | //... 8 | // process x = 1.2*x + x*y 9 | SArray tmp(x); 10 | tmp *= y; 11 | x *= 1.2; 12 | x += tmp; 13 | } 14 | -------------------------------------------------------------------------------- /meta/pow3const.hpp: -------------------------------------------------------------------------------- 1 | // primary template to compute 3 to the Nth 2 | template 3 | struct Pow3 { 4 | static int const value = 3 * Pow3::value; 5 | }; 6 | 7 | // full specialization to end the recursion 8 | template <> 9 | struct Pow3<0> { 10 | static int const value = 1; 11 | }; 12 | -------------------------------------------------------------------------------- /typeoverload/min2.hpp: -------------------------------------------------------------------------------- 1 | #include "isconvertible.hpp" 2 | #include "lessresult.hpp" 3 | 4 | template 5 | EnableIf, bool>, T const&> min( 6 | T const& x, T const& y) { 7 | if (y < x) { 8 | return y; 9 | } 10 | return x; 11 | } 12 | -------------------------------------------------------------------------------- /typeoverload/min3.hpp: -------------------------------------------------------------------------------- 1 | #include "iscontextualbool.hpp" 2 | #include "lessresult.hpp" 3 | 4 | template 5 | EnableIf>, T const&> min( 6 | T const& x, T const& y) { 7 | if (y < x) { 8 | return y; 9 | } 10 | return x; 11 | } 12 | -------------------------------------------------------------------------------- /variant/commontype.hpp: -------------------------------------------------------------------------------- 1 | using std::declval; 2 | 3 | template 4 | class CommonTypeT { 5 | public: 6 | using Type = decltype(true ? declval() : declval()); 7 | }; 8 | 9 | template 10 | using CommonType = typename CommonTypeT::Type; 11 | -------------------------------------------------------------------------------- /variant/variantcopyassign.hpp: -------------------------------------------------------------------------------- 1 | template 2 | Variant& Variant::operator=(Variant const& source) { 3 | if (!source.empty()) { 4 | source.visit([&](auto const& value) { *this = value; }); 5 | } else { 6 | destroy(); 7 | } 8 | return *this; 9 | } 10 | -------------------------------------------------------------------------------- /variant/variantstorageasunion.hpp: -------------------------------------------------------------------------------- 1 | template 2 | union VariantStorage; 3 | 4 | template 5 | union VariantStorage { 6 | Head head; 7 | VariantStorage tail; 8 | }; 9 | 10 | template <> 11 | union VariantStorage<> {}; 12 | -------------------------------------------------------------------------------- /traits/isenum.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsEnumT { 3 | static constexpr bool value = 4 | !IsFundaT::value && !IsPointerT::value && !IsReferenceT::value && 5 | !IsArrayT::value && !IsPointerToMemberT::value && 6 | !IsFunctionT::value && !IsClassT::value; 7 | }; 8 | -------------------------------------------------------------------------------- /traits/removereference.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct RemoveReferenceT { 3 | using Type = T; 4 | }; 5 | 6 | template 7 | struct RemoveReferenceT { 8 | using Type = T; 9 | }; 10 | 11 | template 12 | struct RemoveReferenceT { 13 | using Type = T; 14 | }; 15 | -------------------------------------------------------------------------------- /traits/removevolatile.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct RemoveVolatileT { 3 | using Type = T; 4 | }; 5 | 6 | template 7 | struct RemoveVolatileT { 8 | using Type = T; 9 | }; 10 | 11 | template 12 | using RemoveVolatile = typename RemoveVolatileT::Type; 13 | -------------------------------------------------------------------------------- /basics/len1.hpp: -------------------------------------------------------------------------------- 1 | // number of elements in a raw array: 2 | template 3 | std::size_t len(T (&)[N]) { 4 | return N; 5 | } 6 | 7 | // number of elements for a type having size_type: 8 | template 9 | typename T::size_type len(T const& t) { 10 | return t.size(); 11 | } 12 | -------------------------------------------------------------------------------- /basics/varprint1.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void print() {} 4 | 5 | template 6 | void print(T firstArg, Types... args) { 7 | std::cout << firstArg << '\n'; // print first argument 8 | print(args...); // call print() for remaining arguments 9 | } 10 | -------------------------------------------------------------------------------- /details/nontmpl1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | std::string f(T) { 6 | return "Template"; 7 | } 8 | 9 | std::string f(int&) { return "Nontemplate"; } 10 | 11 | int main() { 12 | int x = 7; 13 | std::cout << f(x) << '\n'; // prints: Nontemplate 14 | } 15 | -------------------------------------------------------------------------------- /traits/isreference.hpp: -------------------------------------------------------------------------------- 1 | #include "ifthenelse.hpp" 2 | #include "islvaluereference.hpp" 3 | #include "isrvaluereference.hpp" 4 | 5 | template 6 | class IsReferenceT 7 | : public IfThenElseT::value, IsLValueReferenceT, 8 | IsRValueReferenceT >::Type {}; 9 | -------------------------------------------------------------------------------- /traits/islvaluereference.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsLValueReferenceT : std::false_type { // by default no lvalue reference 3 | }; 4 | 5 | template 6 | struct IsLValueReferenceT 7 | : std::true_type { // unless T is lvalue references 8 | using BaseT = T; // type referring to 9 | }; 10 | -------------------------------------------------------------------------------- /traits/isrvaluereference.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsRValueReferenceT : std::false_type { // by default no rvalue reference 3 | }; 4 | 5 | template 6 | struct IsRValueReferenceT 7 | : std::true_type { // unless T is rvalue reference 8 | using BaseT = T; // type referring to 9 | }; 10 | -------------------------------------------------------------------------------- /typelist/typelistpopfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PopFrontT; 3 | 4 | template 5 | class PopFrontT> { 6 | public: 7 | using Type = Typelist; 8 | }; 9 | 10 | template 11 | using PopFront = typename PopFrontT::Type; 12 | -------------------------------------------------------------------------------- /typeoverload/min.hpp: -------------------------------------------------------------------------------- 1 | #include "enableif.hpp" 2 | #include "isconvertible.hpp" 3 | #include "lessresult.hpp" 4 | 5 | template 6 | EnableIf, bool>, T const&> min( 7 | T const& x, T const& y) { 8 | if (y < x) { 9 | return y; 10 | } 11 | return x; 12 | } 13 | -------------------------------------------------------------------------------- /details/inject.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int C; 4 | 5 | class C { 6 | private: 7 | int i[2]; 8 | 9 | public: 10 | static int f() { return sizeof(C); } 11 | }; 12 | 13 | int f() { return sizeof(C); } 14 | 15 | int main() { 16 | std::cout << "C::f() = " << C::f() << ',' << " ::f() = " << ::f() << '\n'; 17 | } 18 | -------------------------------------------------------------------------------- /traits/accum1.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | template 5 | T accum(T const* beg, T const* end) { 6 | T total{}; // assume this actually creates a zero value 7 | while (beg != end) { 8 | total += *beg; 9 | ++beg; 10 | } 11 | return total; 12 | } 13 | 14 | #endif // ACCUM_HPP 15 | -------------------------------------------------------------------------------- /tuples/tupleelt1.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class TupleElt { 3 | T value; 4 | 5 | public: 6 | TupleElt() = default; 7 | 8 | template 9 | TupleElt(U&& other) : value(std::forward(other)) {} 10 | 11 | T& get() { return value; } 12 | T const& get() const { return value; } 13 | }; 14 | -------------------------------------------------------------------------------- /variant/variantdestroy17.hpp: -------------------------------------------------------------------------------- 1 | template 2 | void Variant::destroy() { 3 | // call destroy() on each VariantChoice base class; at most one will succeed: 4 | (VariantChoice::destroy(), ...); 5 | 6 | // indicate that the variant does not store a value 7 | this->setDiscriminator(0); 8 | } 9 | -------------------------------------------------------------------------------- /poly/MyClass.hpp: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | private: 3 | int value; 4 | 5 | public: 6 | friend bool operator<(MyClass const& x, MyClass const& y) { 7 | return x.value < y.value; 8 | } 9 | friend std::ostream& operator<<(std::ostream& strm, MyClass const& x) { 10 | strm << x.value; 11 | return strm; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /traits/isclass.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template > 4 | struct IsClassT : std::false_type { // primary template: by default no class 5 | }; 6 | 7 | template 8 | struct IsClassT> // classes can have pointer-to-member 9 | : std::true_type {}; 10 | -------------------------------------------------------------------------------- /basics/foreach.hpp: -------------------------------------------------------------------------------- 1 | template 2 | void foreach (Iter current, Iter end, Callable op) { 3 | while (current != end) { // as long as not reached the end 4 | op(*current); // call passed operator for current element 5 | ++current; // and move iterator to next element 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /traits/ispointer.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsPointerT 3 | : std::false_type { // primary template: by default not a pointer 4 | }; 5 | 6 | template 7 | struct IsPointerT : std::true_type { // partial specialization for pointers 8 | using BaseT = T; // type pointing to 9 | }; 10 | -------------------------------------------------------------------------------- /traits/ispointertomember.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct IsPointerToMemberT 3 | : std::false_type { // by default no pointer-to-member 4 | }; 5 | 6 | template 7 | struct IsPointerToMemberT : std::true_type { // partial specialization 8 | using MemberT = T; 9 | using ClassT = C; 10 | }; 11 | -------------------------------------------------------------------------------- /variant/variantdestroy.hpp: -------------------------------------------------------------------------------- 1 | template 2 | void Variant::destroy() { 3 | // call destroy() on each VariantChoice base class; at most one will succeed: 4 | bool results[] = {VariantChoice::destroy()...}; 5 | // indicate that the variant does not store a value 6 | this->setDiscriminator(0); 7 | } 8 | -------------------------------------------------------------------------------- /variant/variantchoicedestroy.hpp: -------------------------------------------------------------------------------- 1 | template 2 | bool VariantChoice::destroy() { 3 | if (getDerived().getDiscriminator() == Discriminator) { 4 | // if type matches, call placement delete: 5 | getDerived().template getBufferAs()->~T(); 6 | return true; 7 | } 8 | return false; 9 | } 10 | -------------------------------------------------------------------------------- /variant/variantget.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class EmptyVariant : public std::exception {}; 4 | 5 | template 6 | template 7 | T& Variant::get() & { 8 | if (empty()) { 9 | throw EmptyVariant(); 10 | } 11 | 12 | assert(is()); 13 | return *this->template getBufferAs(); 14 | } 15 | -------------------------------------------------------------------------------- /basics/errornovel1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::map coll; 7 | //... 8 | // find the first nonempty string in coll: 9 | auto pos = std::find_if(coll.begin(), coll.end(), 10 | [](std::string const& s) { return s != ""; }); 11 | } 12 | -------------------------------------------------------------------------------- /meta/sqrt1.cpp: -------------------------------------------------------------------------------- 1 | #include "sqrt1.hpp" 2 | #include 3 | 4 | int main() { 5 | std::cout << "Sqrt<16>::value = " << Sqrt<16>::value << '\n'; 6 | std::cout << "Sqrt<25>::value = " << Sqrt<25>::value << '\n'; 7 | std::cout << "Sqrt<42>::value = " << Sqrt<42>::value << '\n'; 8 | std::cout << "Sqrt<1>::value = " << Sqrt<1>::value << '\n'; 9 | } 10 | -------------------------------------------------------------------------------- /typelist/multiply.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct MultiplyT; 3 | 4 | template 5 | struct MultiplyT, CTValue> { 6 | public: 7 | using Type = CTValue; 8 | }; 9 | 10 | template 11 | using Multiply = typename MultiplyT::Type; 12 | -------------------------------------------------------------------------------- /traits/isfundatest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "isfunda.hpp" 3 | 4 | template 5 | void test(T const&) { 6 | if (IsFundaT::value) { 7 | std::cout << "T is a fundamental type" << '\n'; 8 | } else { 9 | std::cout << "T is not a fundamental type" << '\n'; 10 | } 11 | } 12 | 13 | int main() { 14 | test(7); 15 | test("hello"); 16 | } 17 | -------------------------------------------------------------------------------- /tuples/indexsort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::vector strings = {"banana", "apple", "cherry"}; 7 | std::vector indices = {0, 1, 2}; 8 | std::sort(indices.begin(), indices.end(), [&strings](unsigned i, unsigned j) { 9 | return strings[i] < strings[j]; 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /typelist/nthelement.hpp: -------------------------------------------------------------------------------- 1 | // recursive case: 2 | template 3 | class NthElementT : public NthElementT, N - 1> {}; 4 | 5 | // basis case: 6 | template 7 | class NthElementT : public FrontT {}; 8 | 9 | template 10 | using NthElement = typename NthElementT::Type; 11 | -------------------------------------------------------------------------------- /variant/variantvisitresult.hpp: -------------------------------------------------------------------------------- 1 | // an explicitly-provided visitor result type: 2 | template 3 | class VisitResultT { 4 | public: 5 | using Type = R; 6 | }; 7 | 8 | template 9 | using VisitResult = typename VisitResultT::Type; 10 | -------------------------------------------------------------------------------- /basics/invoke.hpp: -------------------------------------------------------------------------------- 1 | #include // for std::forward() 2 | #include // for std::invoke() 3 | 4 | template 5 | decltype(auto) call(Callable&& op, Args&&... args) { 6 | return std::invoke(std::forward(op), // passed callable with 7 | std::forward(args)...); // any additional args 8 | } 9 | -------------------------------------------------------------------------------- /details/funcoverload2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | int f(T) { 5 | return 1; 6 | } 7 | 8 | template 9 | int f(T*) { 10 | return 2; 11 | } 12 | 13 | int main() { 14 | std::cout << f(0); // calls f(T) 15 | std::cout << f(nullptr); // calls f(T) 16 | std::cout << f((int*)nullptr); // calls f(T*) 17 | } 18 | -------------------------------------------------------------------------------- /basics/varprint2.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | void print(T arg) { 5 | std::cout << arg << '\n'; // print passed argument 6 | } 7 | 8 | template 9 | void print(T firstArg, Types... args) { 10 | print(firstArg); // call print() for the first argument 11 | print(args...); // call print() for remaining arguments 12 | } 13 | -------------------------------------------------------------------------------- /traits/accum5.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include "accumtraits4.hpp" 5 | 6 | template > 7 | auto accum(T const* beg, T const* end) { 8 | typename AT::AccT total = AT::zero(); 9 | while (beg != end) { 10 | total += *beg; 11 | ++beg; 12 | } 13 | return total; 14 | } 15 | 16 | #endif // ACCUM_HPP 17 | -------------------------------------------------------------------------------- /tuples/indexlistreverse.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto reverseImpl(Tuple const& t, Valuelist) { 3 | return makeTuple(get(t)...); 4 | } 5 | 6 | template 7 | auto reverse(Tuple const& t) { 8 | return reverseImpl(t, Reverse>()); 9 | } 10 | -------------------------------------------------------------------------------- /basics/len2.hpp: -------------------------------------------------------------------------------- 1 | // number of elements in a raw array: 2 | template 3 | std::size_t len(T (&)[N]) { 4 | return N; 5 | } 6 | 7 | // number of elements for a type having size_type: 8 | template 9 | typename T::size_type len(T const& t) { 10 | return t.size(); 11 | } 12 | 13 | // fallback for all other types: 14 | std::size_t len(...) { return 0; } 15 | -------------------------------------------------------------------------------- /basics/stack6assign.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | Stack& Stack::operator=(Stack const& op2) { 4 | elems.clear(); // remove existing elements 5 | elems.insert(elems.begin(), // insert at the beginning 6 | op2.elems.begin(), // all elements from op2 7 | op2.elems.end()); 8 | return *this; 9 | } 10 | -------------------------------------------------------------------------------- /traits/rparam1.cpp: -------------------------------------------------------------------------------- 1 | #include "rparam.hpp" 2 | #include "rparamcls.hpp" 3 | 4 | // function that allows parameter passing by value or by reference 5 | template 6 | void foo(typename RParam::Type p1, typename RParam::Type p2) { 7 | //... 8 | } 9 | 10 | int main() { 11 | MyClass1 mc1; 12 | MyClass2 mc2; 13 | foo(mc1, mc2); 14 | } 15 | -------------------------------------------------------------------------------- /typelist/largesttypeacc0.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class LargerTypeT : public IfThenElseT= sizeof(U), T, U> {}; 3 | 4 | template 5 | class LargestTypeAccT 6 | : public AccumulateT, LargerTypeT, Front> {}; 7 | 8 | template 9 | using LargestTypeAcc = typename LargestTypeAccT::Type; 10 | -------------------------------------------------------------------------------- /typelist/select.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class SelectT; 3 | 4 | template 5 | class SelectT> { 6 | public: 7 | using Type = Typelist...>; 8 | }; 9 | 10 | template 11 | using Select = typename SelectT::Type; 12 | -------------------------------------------------------------------------------- /basics/specialmemtmpl3.cpp: -------------------------------------------------------------------------------- 1 | #include "specialmemtmpl3.hpp" 2 | 3 | int main() { 4 | std::string s = "sname"; 5 | Person p1(s); // init with string object => calls TMPL-CONSTR 6 | Person p2("tmp"); // init with string literal => calls TMPL-CONSTR 7 | Person p3(p1); // OK => calls COPY-CONSTR 8 | Person p4(std::move(p1)); // OK => calls MOVE-CONST 9 | } 10 | -------------------------------------------------------------------------------- /details/nontmpl2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | std::string f(T&) { 6 | return "Template"; 7 | } 8 | 9 | std::string f(int const&) { return "Nontemplate"; } 10 | 11 | int main() { 12 | int x = 7; 13 | std::cout << f(x) << '\n'; // prints: Template 14 | int const c = 7; 15 | std::cout << f(c) << '\n'; // prints: Nontemplate 16 | } 17 | -------------------------------------------------------------------------------- /tuples/compressedtuple1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tupleelt1.hpp" 4 | #include "tuplestorage3.hpp" 5 | 6 | struct A { 7 | A() { std::cout << "A()" << '\n'; } 8 | }; 9 | 10 | struct B { 11 | B() { std::cout << "B()" << '\n'; } 12 | }; 13 | 14 | int main() { 15 | Tuple t1; 16 | std::cout << sizeof(t1) << " bytes" << '\n'; 17 | } 18 | -------------------------------------------------------------------------------- /tuples/constantget.hpp: -------------------------------------------------------------------------------- 1 | template 2 | T& getHeight(TupleElt& te) { 3 | return te.get(); 4 | } 5 | 6 | template 7 | class Tuple; 8 | 9 | template 10 | auto get(Tuple& t) 11 | -> decltype(getHeight(t)) { 12 | return getHeight(t); 13 | } 14 | -------------------------------------------------------------------------------- /basics/stack5assign.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | Stack& Stack::operator=(Stack const& op2) { 4 | Stack tmp(op2); // create a copy of the assigned stack 5 | 6 | elems.clear(); // remove existing elements 7 | while (!tmp.empty()) { // copy all elements 8 | elems.push_front(tmp.top()); 9 | tmp.pop(); 10 | } 11 | return *this; 12 | } 13 | -------------------------------------------------------------------------------- /meta/duration.hpp: -------------------------------------------------------------------------------- 1 | // duration type for values of type T with unit type U: 2 | template > 3 | class Duration { 4 | public: 5 | using ValueType = T; 6 | using UnitType = typename U::Type; 7 | 8 | private: 9 | ValueType val; 10 | 11 | public: 12 | constexpr Duration(ValueType v = 0) : val(v) {} 13 | constexpr ValueType value() const { return val; } 14 | }; 15 | -------------------------------------------------------------------------------- /overload/initlistovl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void ovl(std::initializer_list) { // \#1 5 | std::cout << "#1\n"; 6 | } 7 | 8 | void ovl(std::initializer_list) { // \#2 9 | std::cout << "#2\n"; 10 | } 11 | 12 | int main() { 13 | ovl({'h', 'e', 'l', 'l', 'o', '\0'}); // prints \#1 14 | ovl({'h', 'e', 'l', 'l', 'o', 0}); // prints \#2 15 | } 16 | -------------------------------------------------------------------------------- /traits/plus3.hpp: -------------------------------------------------------------------------------- 1 | #include "hasplus.hpp" 2 | 3 | template ::value> 4 | struct PlusResultT { // primary template, used when HasPlusT yields true 5 | using Type = decltype(std::declval() + std::declval()); 6 | }; 7 | 8 | template 9 | struct PlusResultT { // partial specialization, used otherwise 10 | }; 11 | -------------------------------------------------------------------------------- /tuples/tuplestorage1.hpp: -------------------------------------------------------------------------------- 1 | // recursive case: 2 | template 3 | class Tuple : private Tuple { 4 | private: 5 | Head head; 6 | 7 | public: 8 | Head& getHead() { return head; } 9 | Head const& getHead() const { return head; } 10 | Tuple& getTail() { return *this; } 11 | Tuple const& getTail() const { return *this; } 12 | }; 13 | -------------------------------------------------------------------------------- /basics/myfirst2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MYFIRST_HPP 2 | #define MYFIRST_HPP 3 | 4 | #include 5 | #include 6 | 7 | // declaration of template 8 | template 9 | void printTypeof(T const&); 10 | 11 | // implementation/definition of template 12 | template 13 | void printTypeof(T const& x) { 14 | std::cout << typeid(x).name() << '\n'; 15 | } 16 | 17 | #endif // MYFIRST_HPP 18 | -------------------------------------------------------------------------------- /traits/addreference.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct AddLValueReferenceT { 3 | using Type = T&; 4 | }; 5 | 6 | template 7 | using AddLValueReference = typename AddLValueReferenceT::Type; 8 | 9 | template 10 | struct AddRValueReferenceT { 11 | using Type = T&&; 12 | }; 13 | 14 | template 15 | using AddRValueReference = typename AddRValueReferenceT::Type; 16 | -------------------------------------------------------------------------------- /typelist/insertionsorttest.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct SmallerThanT { 3 | static constexpr bool value = sizeof(T) < sizeof(U); 4 | }; 5 | 6 | void testInsertionSort() { 7 | using Types = Typelist; 8 | using ST = InsertionSort; 9 | std::cout << std::is_same>::value 10 | << '\n'; 11 | } 12 | -------------------------------------------------------------------------------- /typelist/typelistpushback.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PushBackT; 3 | 4 | template 5 | class PushBackT, NewElement> { 6 | public: 7 | using Type = Typelist; 8 | }; 9 | 10 | template 11 | using PushBack = typename PushBackT::Type; 12 | -------------------------------------------------------------------------------- /details/max.cpp: -------------------------------------------------------------------------------- 1 | template 2 | T max(T a, T b) { 3 | return b < a ? a : b; 4 | } 5 | 6 | int main() { 7 | ::max(1.0, -3.0); // explicitly specify template argument 8 | ::max(1.0, -3.0); // template argument is implicitly deduced to be double 9 | ::max(1.0, 3.0); // the explicit inhibits the deduction; 10 | // hence the result has type int 11 | } 12 | -------------------------------------------------------------------------------- /poly/coord.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COORD_HPP 2 | #define COORD_HPP 3 | #include 4 | 5 | class Coord { 6 | private: 7 | int x, y; 8 | 9 | public: 10 | Coord(int i1, int i2) : x(i1), y(i2) {} 11 | friend Coord operator-(Coord const& c1, Coord const& c2) { 12 | return Coord(c1.x - c2.x, c1.y - c2.y); 13 | } 14 | Coord abs() { return Coord(std::abs(x), std::abs(y)); } 15 | }; 16 | #endif // COORD_HPP 17 | -------------------------------------------------------------------------------- /typelist/typelistpushfront.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class PushFrontT; 3 | 4 | template 5 | class PushFrontT, NewElement> { 6 | public: 7 | using Type = Typelist; 8 | }; 9 | 10 | template 11 | using PushFront = typename PushFrontT::Type; 12 | -------------------------------------------------------------------------------- /basics/printcoll.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // print elements of an STL container 4 | template 5 | void printcoll(T const& coll) { 6 | typename T::const_iterator pos; // iterator to iterate over coll 7 | typename T::const_iterator end(coll.end()); // end position 8 | for (pos = coll.begin(); pos != end; ++pos) { 9 | std::cout << *pos << ' '; 10 | } 11 | std::cout << '\n'; 12 | } 13 | -------------------------------------------------------------------------------- /inherit/countertest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "objectcounter.hpp" 3 | 4 | template 5 | class MyString : public ObjectCounter> { 6 | //... 7 | }; 8 | 9 | int main() { 10 | MyString s1, s2; 11 | MyString ws; 12 | std::cout << "num of MyString: " << MyString::live() << '\n'; 13 | std::cout << "num of MyString: " << ws.live() << '\n'; 14 | } 15 | -------------------------------------------------------------------------------- /basics/max1.cpp: -------------------------------------------------------------------------------- 1 | #include "max1.hpp" 2 | #include 3 | #include 4 | 5 | int main() { 6 | int i = 42; 7 | std::cout << "max(7,i): " << ::max(7, i) << '\n'; 8 | 9 | double f1 = 3.4; 10 | double f2 = -6.7; 11 | std::cout << "max(f1,f2): " << ::max(f1, f2) << '\n'; 12 | 13 | std::string s1 = "mathematics"; 14 | std::string s2 = "math"; 15 | std::cout << "max(s1,s2): " << ::max(s1, s2) << '\n'; 16 | } 17 | -------------------------------------------------------------------------------- /traits/accum0.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include 5 | 6 | template 7 | auto accum(Iter start, Iter end) { 8 | using VT = typename std::iterator_traits::value_type; 9 | 10 | VT total{}; // assume this actually creates a zero value 11 | while (start != end) { 12 | total += *start; 13 | ++start; 14 | } 15 | return total; 16 | } 17 | 18 | #endif // ACCUM_HPP 19 | -------------------------------------------------------------------------------- /tuples/makeindexlist.hpp: -------------------------------------------------------------------------------- 1 | // recursive case 2 | template > 3 | struct MakeIndexListT 4 | : MakeIndexListT>> {}; 5 | 6 | // basis case 7 | template 8 | struct MakeIndexListT<0, Result> { 9 | using Type = Result; 10 | }; 11 | 12 | template 13 | using MakeIndexList = typename MakeIndexListT::Type; 14 | -------------------------------------------------------------------------------- /basics/stack7assign.hpp: -------------------------------------------------------------------------------- 1 | template 2 | template 3 | Stack& Stack::operator=(Stack const& op2) { 4 | elems.clear(); // remove existing elements 5 | elems.insert(elems.begin(), // insert at the beginning 6 | op2.elems.begin(), // all elements from op2 7 | op2.elems.end()); 8 | return *this; 9 | } 10 | -------------------------------------------------------------------------------- /traits/hasbegin.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | #include // for declval 3 | 4 | // primary template: 5 | template > 6 | struct HasBeginT : std::false_type {}; 7 | 8 | // partial specialization (may be SFINAE'd away): 9 | template 10 | struct HasBeginT().begin())>> 11 | : std::true_type {}; 12 | -------------------------------------------------------------------------------- /basics/stack8decl.hpp: -------------------------------------------------------------------------------- 1 | template class Cont = std::deque> 2 | class Stack { 3 | private: 4 | Cont elems; // elements 5 | 6 | public: 7 | void push(T const&); // push element 8 | void pop(); // pop element 9 | T const& top() const; // return top element 10 | bool empty() const { // return whether the stack is empty 11 | return elems.empty(); 12 | } 13 | //... 14 | }; 15 | -------------------------------------------------------------------------------- /inherit/projectioniterator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::vector authors = { 7 | {"David", "Vandevoorde"}, {"Nicolai", "Josuttis"}, {"Douglas", "Gregor"}}; 8 | 9 | std::copy(project(authors.begin(), &Person::firstName), 10 | project(authors.end(), &Person::firstName), 11 | std::ostream_iterator(std::cout, "\n")); 12 | } 13 | -------------------------------------------------------------------------------- /traits/elementtype.cpp: -------------------------------------------------------------------------------- 1 | #include "elementtype.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | void printElementType(T const& c) { 8 | std::cout << "Container of " << typeid(typename ElementT::Type).name() 9 | << " elements.\n"; 10 | } 11 | 12 | int main() { 13 | std::vector s; 14 | printElementType(s); 15 | int arr[42]; 16 | printElementType(arr); 17 | } 18 | -------------------------------------------------------------------------------- /names/anglebrackethack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct X { 5 | static int const c = 2; 6 | }; 7 | 8 | template <> 9 | struct X<0> { 10 | typedef int c; 11 | }; 12 | 13 | template 14 | struct Y { 15 | static int const c = 3; 16 | }; 17 | 18 | static int const c = 4; 19 | 20 | int main() { 21 | std::cout << (Y>::c > ::c > ::c) << ' '; 22 | std::cout << (Y>::c > ::c > ::c) << '\n'; 23 | } 24 | -------------------------------------------------------------------------------- /variant/variantdefaultctor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "variant-all.hpp" 3 | 4 | int main() { 5 | Variant v; 6 | if (v.is()) { 7 | std::cout << "Default-constructed v stores the int " << v.get() 8 | << '\n'; 9 | } 10 | Variant v2; 11 | if (v2.is()) { 12 | std::cout << "Default-constructed v2 stores the double " << v2.get() 13 | << '\n'; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /inherit/wrapper.cpp: -------------------------------------------------------------------------------- 1 | class S {}; 2 | 3 | template 4 | class Wrapper { 5 | private: 6 | T object; 7 | 8 | public: 9 | Wrapper(T obj) : object(obj) { // implicit conversion from T to Wrapper 10 | } 11 | friend void foo(Wrapper const&) {} 12 | }; 13 | 14 | int main() { 15 | S s; 16 | Wrapper w(s); 17 | foo(w); // OK: Wrapper is a class associated with w 18 | foo(s); // ERROR: Wrapper is not associated with s 19 | } 20 | -------------------------------------------------------------------------------- /traits/accumtraits3.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct AccumulationTraits; 3 | 4 | template <> 5 | struct AccumulationTraits { 6 | using AccT = int; 7 | static AccT const zero = 0; 8 | }; 9 | 10 | template <> 11 | struct AccumulationTraits { 12 | using AccT = int; 13 | static AccT const zero = 0; 14 | }; 15 | 16 | template <> 17 | struct AccumulationTraits { 18 | using AccT = long; 19 | static AccT const zero = 0; 20 | }; 21 | //... 22 | -------------------------------------------------------------------------------- /tuples/tuplesorttest.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class SmallerThanT { 5 | public: 6 | static constexpr bool value = sizeof(T) < sizeof(U); 7 | }; 8 | 9 | void testTupleSort() { 10 | auto t1 = makeTuple(17LL, std::complex(42, 77), 'c', 42, 7.7); 11 | std::cout << t1 << '\n'; 12 | auto t2 = sort(t1); // t2 is Tuple 13 | std::cout << "sorted by size: " << t2 << '\n'; 14 | } 15 | -------------------------------------------------------------------------------- /typelist/conslisttest.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct SmallerThanT { 3 | static constexpr bool value = sizeof(T) < sizeof(U); 4 | }; 5 | 6 | void conslisttest() { 7 | using ConsList = Cons>>>; 8 | using SortedTypes = InsertionSort; 9 | using Expected = Cons>>>; 10 | std::cout << std::is_same::value << '\n'; 11 | } 12 | -------------------------------------------------------------------------------- /basics/tmplparamref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | void tmplParamIsReference(T) { 5 | std::cout << "T is reference: " << std::is_reference_v << '\n'; 6 | } 7 | 8 | int main() { 9 | std::cout << std::boolalpha; 10 | int i; 11 | int& r = i; 12 | tmplParamIsReference(i); // false 13 | tmplParamIsReference(r); // false 14 | tmplParamIsReference(i); // true 15 | tmplParamIsReference(r); // true 16 | } 17 | -------------------------------------------------------------------------------- /inherit/ebco1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Empty { 4 | using Int = int; // type alias members don't make a class nonempty 5 | }; 6 | 7 | class EmptyToo : public Empty {}; 8 | 9 | class EmptyThree : public EmptyToo {}; 10 | 11 | int main() { 12 | std::cout << "sizeof(Empty): " << sizeof(Empty) << '\n'; 13 | std::cout << "sizeof(EmptyToo): " << sizeof(EmptyToo) << '\n'; 14 | std::cout << "sizeof(EmptyThree): " << sizeof(EmptyThree) << '\n'; 15 | } 16 | -------------------------------------------------------------------------------- /basics/stack1test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack1.hpp" 4 | 5 | int main() { 6 | Stack intStack; // stack of ints 7 | Stack stringStack; // stack of strings 8 | 9 | // manipulate int stack 10 | intStack.push(7); 11 | std::cout << intStack.top() << '\n'; 12 | 13 | // manipulate string stack 14 | stringStack.push("hello"); 15 | std::cout << stringStack.top() << '\n'; 16 | stringStack.pop(); 17 | } 18 | -------------------------------------------------------------------------------- /inherit/ebco2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Empty { 4 | using Int = int; // type alias members don't make a class nonempty 5 | }; 6 | 7 | class EmptyToo : public Empty {}; 8 | 9 | class NonEmpty : public Empty, public EmptyToo {}; 10 | 11 | int main() { 12 | std::cout << "sizeof(Empty): " << sizeof(Empty) << '\n'; 13 | std::cout << "sizeof(EmptyToo): " << sizeof(EmptyToo) << '\n'; 14 | std::cout << "sizeof(NonEmpty): " << sizeof(NonEmpty) << '\n'; 15 | } 16 | -------------------------------------------------------------------------------- /poly/statichier.hpp: -------------------------------------------------------------------------------- 1 | #include "coord.hpp" 2 | 3 | // concrete geometric object class Circle 4 | // - \bfseries not derived from any class 5 | class Circle { 6 | public: 7 | void draw() const; 8 | Coord center_of_gravity() const; 9 | //... 10 | }; 11 | 12 | // concrete geometric object class Line 13 | // - \bfseries not derived from any class 14 | class Line { 15 | public: 16 | void draw() const; 17 | Coord center_of_gravity() const; 18 | //... 19 | }; 20 | //... 21 | -------------------------------------------------------------------------------- /traits/hassizetype.hpp: -------------------------------------------------------------------------------- 1 | #include // defines true_type and false_type 2 | 3 | // helper to ignore any number of template parameters: 4 | template 5 | using VoidT = void; 6 | 7 | // primary template: 8 | template > 9 | struct HasSizeTypeT : std::false_type {}; 10 | 11 | // partial specialization (may be SFINAE'd away): 12 | template 13 | struct HasSizeTypeT> : std::true_type {}; 14 | -------------------------------------------------------------------------------- /basics/addspace.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class AddSpace { 3 | private: 4 | T const& ref; // refer to argument passed in constructor 5 | public: 6 | AddSpace(T const& r) : ref(r) {} 7 | friend std::ostream& operator<<(std::ostream& os, AddSpace s) { 8 | return os << s.ref << ' '; // output passed argument and a space 9 | } 10 | }; 11 | 12 | template 13 | void print(Args... args) { 14 | (std::cout << ... << AddSpace(args)) << '\n'; 15 | } 16 | -------------------------------------------------------------------------------- /meta/ratioadd.hpp: -------------------------------------------------------------------------------- 1 | // implementation of adding two ratios: 2 | template 3 | struct RatioAddImpl { 4 | private: 5 | static constexpr unsigned den = R1::den * R2::den; 6 | static constexpr unsigned num = R1::num * R2::den + R2::num * R1::den; 7 | 8 | public: 9 | typedef Ratio Type; 10 | }; 11 | 12 | // using declaration for convenient usage: 13 | template 14 | using RatioAdd = typename RatioAddImpl::Type; 15 | -------------------------------------------------------------------------------- /traits/accum2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include "accumtraits2.hpp" 5 | 6 | template 7 | auto accum(T const* beg, T const* end) { 8 | // return type is traits of the element type 9 | using AccT = typename AccumulationTraits::AccT; 10 | 11 | AccT total{}; // assume this actually creates a zero value 12 | while (beg != end) { 13 | total += *beg; 14 | ++beg; 15 | } 16 | return total; 17 | } 18 | 19 | #endif // ACCUM_HPP 20 | -------------------------------------------------------------------------------- /traits/rparam.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RPARAM_HPP 2 | #define RPARAM_HPP 3 | 4 | #include 5 | #include "ifthenelse.hpp" 6 | 7 | template 8 | struct RParam { 9 | using Type = IfThenElse<(sizeof(T) <= 2 * sizeof(void*) && 10 | std::is_trivially_copy_constructible::value && 11 | std::is_trivially_move_constructible::value), 12 | T, T const&>; 13 | }; 14 | 15 | #endif // RPARAM_HPP 16 | -------------------------------------------------------------------------------- /traits/hastype.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | 3 | #define DEFINE_HAS_TYPE(MemType) \ 4 | template > \ 5 | struct HasTypeT_##MemType : std::false_type {}; \ 6 | template \ 7 | struct HasTypeT_##MemType> \ 8 | : std::true_type {} // ; intentionally skipped 9 | -------------------------------------------------------------------------------- /typelist/typelistreverse.hpp: -------------------------------------------------------------------------------- 1 | template ::value> 2 | class ReverseT; 3 | 4 | template 5 | using Reverse = typename ReverseT::Type; 6 | 7 | // recursive case: 8 | template 9 | class ReverseT 10 | : public PushBackT>, Front> {}; 11 | 12 | // basis case: 13 | template 14 | class ReverseT { 15 | public: 16 | using Type = List; 17 | }; 18 | -------------------------------------------------------------------------------- /basics/cref.cpp: -------------------------------------------------------------------------------- 1 | #include // for std::cref() 2 | #include 3 | #include 4 | 5 | void printString(std::string const& s) { std::cout << s << '\n'; } 6 | 7 | template 8 | void printT(T arg) { 9 | printString(arg); // might convert arg back to std::string 10 | } 11 | 12 | int main() { 13 | std::string s = "hello"; 14 | printT(s); // print s passed by value 15 | printT(std::cref(s)); // print s passed ``as if by reference'' 16 | } 17 | -------------------------------------------------------------------------------- /basics/message.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template // take value of any possible nontype parameter (since C++17) 4 | class Message { 5 | public: 6 | void print() { std::cout << T << '\n'; } 7 | }; 8 | 9 | int main() { 10 | Message<42> msg1; 11 | msg1.print(); // initialize with int 42 and print that value 12 | 13 | static char const s[] = "hello"; 14 | Message msg2; // initialize with char~const[6] "hello" 15 | msg2.print(); // and print that value 16 | } 17 | -------------------------------------------------------------------------------- /details/adl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace X { 4 | template 5 | void f(T); 6 | } 7 | 8 | namespace N { 9 | using namespace X; 10 | enum E { e1 }; 11 | void f(E) { std::cout << "N::f(N::E) called\n"; } 12 | } // namespace N 13 | 14 | void f(int) { std::cout << "::f(int) called\n"; } 15 | 16 | int main() { 17 | ::f(N::e1); // qualified function name: no ADL 18 | f(N::e1); // ordinary lookup finds ::f() and ADL finds N::f(), 19 | } // the latter is preferred 20 | -------------------------------------------------------------------------------- /inherit/equalitycomparable.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class EqualityComparable { 3 | public: 4 | friend bool operator!=(Derived const& x1, Derived const& x2) { 5 | return !(x1 == x2); 6 | } 7 | }; 8 | 9 | class X : public EqualityComparable { 10 | public: 11 | friend bool operator==(X const& x1, X const& x2) { 12 | // implement logic for comparing two objects of type X 13 | } 14 | }; 15 | 16 | int main() { 17 | X x1, x2; 18 | if (x1 != x2) { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /traits/accum3.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include "accumtraits3.hpp" 5 | 6 | template 7 | auto accum(T const* beg, T const* end) { 8 | // return type is traits of the element type 9 | using AccT = typename AccumulationTraits::AccT; 10 | 11 | AccT total = AccumulationTraits::zero; // init total by trait value 12 | while (beg != end) { 13 | total += *beg; 14 | ++beg; 15 | } 16 | return total; 17 | } 18 | 19 | #endif // ACCUM_HPP 20 | -------------------------------------------------------------------------------- /traits/hasless.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | #include // for declval 3 | 4 | // primary template: 5 | template > 6 | struct HasLessT : std::false_type {}; 7 | 8 | // partial specialization (may be SFINAE'd away): 9 | template 10 | struct HasLessT() < std::declval())>> 12 | : std::true_type {}; 13 | -------------------------------------------------------------------------------- /traits/hasmember.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | 3 | #define DEFINE_HAS_MEMBER(Member) \ 4 | template > \ 5 | struct HasMemberT_##Member : std::false_type {}; \ 6 | template \ 7 | struct HasMemberT_##Member> \ 8 | : std::true_type {} // ; intentionally skipped 9 | -------------------------------------------------------------------------------- /traits/hasplus.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | #include // for declval 3 | 4 | // primary template: 5 | template > 6 | struct HasPlusT : std::false_type {}; 7 | 8 | // partial specialization (may be SFINAE'd away): 9 | template 10 | struct HasPlusT() + std::declval())>> 12 | : std::true_type {}; 13 | -------------------------------------------------------------------------------- /tuples/pushback.hpp: -------------------------------------------------------------------------------- 1 | // basis case 2 | template 3 | Tuple pushBack(Tuple<> const&, V const& value) { 4 | return Tuple(value); 5 | } 6 | 7 | // recursive case 8 | template 9 | Tuple pushBack(Tuple const& tuple, 10 | V const& value) { 11 | return Tuple(tuple.getHead(), 12 | pushBack(tuple.getTail(), value)); 13 | } 14 | -------------------------------------------------------------------------------- /bridge/tryequals.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "isequalitycomparable.hpp" 3 | 4 | template ::value> 5 | struct TryEquals { 6 | static bool equals(T const& x1, T const& x2) { return x1 == x2; } 7 | }; 8 | 9 | class NotEqualityComparable : public std::exception {}; 10 | 11 | template 12 | struct TryEquals { 13 | static bool equals(T const& x1, T const& x2) { 14 | throw NotEqualityComparable(); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /basics/foreachinvoke.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void foreach (Iter current, Iter end, Callable op, Args const&... args) { 6 | while (current != end) { // as long as not reached the end of the elements 7 | std::invoke(op, // call passed callable with 8 | args..., // any additional args 9 | *current); // and the current element 10 | ++current; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /basics/stack5decl.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Stack { 3 | private: 4 | std::deque elems; // elements 5 | 6 | public: 7 | void push(T const&); // push element 8 | void pop(); // pop element 9 | T const& top() const; // return top element 10 | bool empty() const { // return whether the stack is empty 11 | return elems.empty(); 12 | } 13 | 14 | // assign stack of elements of type T2 15 | template 16 | Stack& operator=(Stack const&); 17 | }; 18 | -------------------------------------------------------------------------------- /traits/accum6.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include "accumtraits4.hpp" 5 | #include "sumpolicy1.hpp" 6 | 7 | template > 9 | auto accum(T const* beg, T const* end) { 10 | using AccT = typename Traits::AccT; 11 | AccT total = Traits::zero(); 12 | while (beg != end) { 13 | Policy::accumulate(total, *beg); 14 | ++beg; 15 | } 16 | return total; 17 | } 18 | 19 | #endif // ACCUM_HPP 20 | -------------------------------------------------------------------------------- /traits/isdefaultconstructible1.hpp: -------------------------------------------------------------------------------- 1 | #include "issame.hpp" 2 | 3 | template 4 | struct IsDefaultConstructibleT { 5 | private: 6 | // test() trying substitute call of a default constructor for T passed as U: 7 | template 8 | static char test(void*); 9 | // test() fallback: 10 | template 11 | static long test(...); 12 | 13 | public: 14 | static constexpr bool value = 15 | IsSameT(nullptr)), char>::value; 16 | }; 17 | -------------------------------------------------------------------------------- /debugging/hasderef.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type and false_type 2 | #include // for declval() 3 | 4 | template 5 | class HasDereference { 6 | private: 7 | template 8 | struct Identity; 9 | template 10 | static std::true_type test(Identity())>*); 11 | template 12 | static std::false_type test(...); 13 | 14 | public: 15 | static constexpr bool value = decltype(test(nullptr))::value; 16 | }; 17 | -------------------------------------------------------------------------------- /inherit/listnodeiterator0.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class ListNodeIterator 3 | : public IteratorFacade, T, std::forward_iterator_tag> { 4 | ListNode* current = nullptr; 5 | 6 | public: 7 | T& dereference() const { return current->value; } 8 | void increment() { current = current->next; } 9 | bool equals(ListNodeIterator const& other) const { 10 | return current == other.current; 11 | } 12 | ListNodeIterator(ListNode* current = nullptr) : current(current) {} 13 | }; 14 | -------------------------------------------------------------------------------- /traits/accum6.cpp: -------------------------------------------------------------------------------- 1 | #include "accum6.hpp" 2 | #include 3 | 4 | class MultPolicy { 5 | public: 6 | template 7 | static void accumulate(T1& total, T2 const& value) { 8 | total *= value; 9 | } 10 | }; 11 | 12 | int main() { 13 | // create array of 5 integer values 14 | int num[] = {1, 2, 3, 4, 5}; 15 | 16 | // print product of all values 17 | std::cout << "the product of the integer values is " 18 | << accum(num, num + 5) << '\n'; 19 | } 20 | -------------------------------------------------------------------------------- /traits/hasmember.cpp: -------------------------------------------------------------------------------- 1 | #include "hasmember.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | DEFINE_HAS_MEMBER(size); 8 | DEFINE_HAS_MEMBER(first); 9 | 10 | int main() { 11 | std::cout << "int::size: " << HasMemberT_size::value << '\n'; 12 | std::cout << "std::vector::size: " 13 | << HasMemberT_size>::value << '\n'; 14 | std::cout << "std::pair::first: " 15 | << HasMemberT_first>::value << '\n'; 16 | } 17 | -------------------------------------------------------------------------------- /tuples/apply.hpp: -------------------------------------------------------------------------------- 1 | template 2 | auto applyImpl(F f, Tuple const& t, 3 | Valuelist) 4 | -> decltype(f(get(t)...)) { 5 | return f(get(t)...); 6 | } 7 | 8 | template 9 | auto apply(F f, Tuple const& t) 10 | -> decltype(applyImpl(f, t, MakeIndexList())) { 11 | return applyImpl(f, t, MakeIndexList()); 12 | } 13 | -------------------------------------------------------------------------------- /variant/variant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "variant-all.hpp" 4 | 5 | int main() { 6 | Variant field(17); 7 | if (field.is()) { 8 | std::cout << "Field stores the integer " << field.get() << std::endl; 9 | } 10 | field = 42; // assign value of same type 11 | field = "hello"; // assign value of different type 12 | std::cout << "Field now stores the string \"" << field.get() 13 | << '\"' << std::endl; 14 | } 15 | -------------------------------------------------------------------------------- /exprtmpl/exprscalar.hpp: -------------------------------------------------------------------------------- 1 | // class for objects that represent scalars: 2 | template 3 | class A_Scalar { 4 | private: 5 | T const& s; // value of the scalar 6 | 7 | public: 8 | // constructor initializes value 9 | constexpr A_Scalar(T const& v) : s(v) {} 10 | 11 | // for index operations, the scalar is the value of each element 12 | constexpr T const& operator[](std::size_t) const { return s; } 13 | 14 | // scalars have zero as size 15 | constexpr std::size_t size() const { return 0; }; 16 | }; 17 | -------------------------------------------------------------------------------- /traits/hasvarious.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and void_t 2 | #include // for declval 3 | 4 | // primary template: 5 | template > 6 | struct HasVariousT : std::false_type {}; 7 | 8 | // partial specialization (may be SFINAE'd away): 9 | template 10 | struct HasVariousT< 11 | T, std::void_t().begin()), 12 | typename T::difference_type, typename T::iterator>> 13 | : std::true_type {}; 14 | -------------------------------------------------------------------------------- /details/variadicoverload.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | int f(T*) { 5 | return 1; 6 | } 7 | 8 | template 9 | int f(Ts...) { 10 | return 2; 11 | } 12 | 13 | template 14 | int f(Ts*...) { 15 | return 3; 16 | } 17 | 18 | int main() { 19 | std::cout << f(0, 0.0); // calls f<>(Ts...) 20 | std::cout << f((int*)nullptr, (double*)nullptr); // calls f<>(Ts*...) 21 | std::cout << f((int*)nullptr); // calls f<>(T*) 22 | } 23 | -------------------------------------------------------------------------------- /traits/isdefaultconstructible3.hpp: -------------------------------------------------------------------------------- 1 | #include // defines true_type and false_type 2 | #include "issame.hpp" 3 | 4 | // helper to ignore any number of template parameters: 5 | template 6 | using VoidT = void; 7 | 8 | // primary template: 9 | template > 10 | struct IsDefaultConstructibleT : std::false_type {}; 11 | 12 | // partial specialization (may be SFINAE'd away): 13 | template 14 | struct IsDefaultConstructibleT> : std::true_type {}; 15 | -------------------------------------------------------------------------------- /basics/referror1.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class RefMem { 3 | private: 4 | T zero; 5 | 6 | public: 7 | RefMem() : zero{Z} {} 8 | }; 9 | 10 | int null = 0; 11 | 12 | int main() { 13 | RefMem rm1, rm2; 14 | rm1 = rm2; // OK 15 | 16 | RefMem rm3; // ERROR: invalid default value for N 17 | RefMem rm4; // ERROR: invalid default value for N 18 | 19 | extern int null; 20 | RefMem rm5, rm6; 21 | rm5 = rm6; // ERROR: operator= is deleted due to reference member 22 | } 23 | -------------------------------------------------------------------------------- /traits/accum7.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ACCUM_HPP 2 | #define ACCUM_HPP 3 | 4 | #include "accumtraits4.hpp" 5 | #include "sumpolicy2.hpp" 6 | 7 | template class Policy = SumPolicy, 8 | typename Traits = AccumulationTraits> 9 | auto accum(T const* beg, T const* end) { 10 | using AccT = typename Traits::AccT; 11 | AccT total = Traits::zero(); 12 | while (beg != end) { 13 | Policy::accumulate(total, *beg); 14 | ++beg; 15 | } 16 | return total; 17 | } 18 | 19 | #endif // ACCUM_HPP 20 | -------------------------------------------------------------------------------- /tuples/tupleeq.hpp: -------------------------------------------------------------------------------- 1 | // basis case: 2 | bool operator==(Tuple<> const&, Tuple<> const&) { 3 | // empty tuples are always equivalent 4 | return true; 5 | } 6 | 7 | // recursive case: 8 | template > 10 | bool operator==(Tuple const& lhs, 11 | Tuple const& rhs) { 12 | return lhs.getHead() == rhs.getHead() && lhs.getTail() == rhs.getTail(); 13 | } 14 | -------------------------------------------------------------------------------- /basics/isprime11.hpp: -------------------------------------------------------------------------------- 1 | constexpr bool doIsPrime(unsigned p, 2 | unsigned d) // p: number to check, d: current divisor 3 | { 4 | return d != 2 ? (p % d != 0) && 5 | doIsPrime(p, d - 1) // check this and smaller divisors 6 | : (p % 2 != 0); // end recursion if divisor is 2 7 | } 8 | 9 | constexpr bool isPrime(unsigned p) { 10 | return p < 4 ? !(p < 2) // handle special cases 11 | : doIsPrime(p, p / 2); // start recursion with divisor from p/2 12 | } 13 | -------------------------------------------------------------------------------- /basics/stack3test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack3.hpp" 4 | 5 | int main() { 6 | // stack of ints: 7 | Stack intStack; 8 | 9 | // stack of doubles using a std::deque<> to manage the elements 10 | Stack> dblStack; 11 | 12 | // manipulate int stack 13 | intStack.push(7); 14 | std::cout << intStack.top() << '\n'; 15 | intStack.pop(); 16 | 17 | // manipulate double stack 18 | dblStack.push(42.42); 19 | std::cout << dblStack.top() << '\n'; 20 | dblStack.pop(); 21 | } 22 | -------------------------------------------------------------------------------- /deduce/resulttypetmpl.cpp: -------------------------------------------------------------------------------- 1 | template 2 | auto addA(T t, U u) -> decltype(t + u) { 3 | return t + u; 4 | } 5 | 6 | void addA(...); 7 | 8 | template 9 | auto addB(T t, U u) -> decltype(auto) { 10 | return t + u; 11 | } 12 | 13 | void addB(...); 14 | 15 | struct X {}; 16 | 17 | using AddResultA = decltype(addA(X(), X())); // OK: AddResultA is void 18 | using AddResultB = decltype(addB(X(), X())); // ERROR: instantiation of addB 19 | // is ill-formed 20 | -------------------------------------------------------------------------------- /traits/accumtraits2.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct AccumulationTraits; 3 | 4 | template <> 5 | struct AccumulationTraits { 6 | using AccT = int; 7 | }; 8 | 9 | template <> 10 | struct AccumulationTraits { 11 | using AccT = int; 12 | }; 13 | 14 | template <> 15 | struct AccumulationTraits { 16 | using AccT = long; 17 | }; 18 | 19 | template <> 20 | struct AccumulationTraits { 21 | using AccT = unsigned long; 22 | }; 23 | 24 | template <> 25 | struct AccumulationTraits { 26 | using AccT = double; 27 | }; 28 | -------------------------------------------------------------------------------- /traits/decay.hpp: -------------------------------------------------------------------------------- 1 | #include "removecv.hpp" 2 | 3 | template 4 | struct DecayT : RemoveCVT {}; 5 | 6 | template 7 | struct DecayT { 8 | using Type = T*; 9 | }; 10 | 11 | template 12 | struct DecayT { 13 | using Type = T*; 14 | }; 15 | 16 | template 17 | struct DecayT { 18 | using Type = R (*)(Args...); 19 | }; 20 | 21 | template 22 | struct DecayT { 23 | using Type = R (*)(Args..., ...); 24 | }; 25 | -------------------------------------------------------------------------------- /traits/isarray.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct IsArrayT : std::false_type { // primary template: not an array 5 | }; 6 | 7 | template 8 | struct IsArrayT : std::true_type { // partial specialization for arrays 9 | using BaseT = T; 10 | static constexpr std::size_t size = N; 11 | }; 12 | 13 | template 14 | struct IsArrayT 15 | : std::true_type { // partial specialization for unbound arrays 16 | using BaseT = T; 17 | static constexpr std::size_t size = 0; 18 | }; 19 | -------------------------------------------------------------------------------- /traits/rparamcls.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "rparam.hpp" 3 | 4 | class MyClass1 { 5 | public: 6 | MyClass1() {} 7 | MyClass1(MyClass1 const&) { 8 | std::cout << "MyClass1 copy constructor called\n"; 9 | } 10 | }; 11 | 12 | class MyClass2 { 13 | public: 14 | MyClass2() {} 15 | MyClass2(MyClass2 const&) { 16 | std::cout << "MyClass2 copy constructor called\n"; 17 | } 18 | }; 19 | 20 | // pass MyClass2 objects with RParam<> by value 21 | template <> 22 | class RParam { 23 | public: 24 | using Type = MyClass2; 25 | }; 26 | -------------------------------------------------------------------------------- /bridge/forupto1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void forUpTo(int n, F f) { 6 | for (int i = 0; i != n; ++i) { 7 | f(i); // call passed function f for i 8 | } 9 | } 10 | 11 | void printInt(int i) { std::cout << i << ' '; } 12 | 13 | int main() { 14 | std::vector values; 15 | 16 | // insert values from 0 to 4: 17 | forUpTo(5, [&values](int i) { values.push_back(i); }); 18 | 19 | // print elements: 20 | forUpTo(5, 21 | printInt); // prints 0 1 2 3 4 22 | std::cout << '\n'; 23 | } 24 | -------------------------------------------------------------------------------- /tuples/copycountertest.hpp: -------------------------------------------------------------------------------- 1 | void copycountertest() { 2 | Tuple, CopyCounter<1>, CopyCounter<2>, CopyCounter<3>, 3 | CopyCounter<4>> 4 | copies; 5 | auto reversed = reverse(copies); 6 | std::cout << "0: " << CopyCounter<0>::numCopies << " copies\n"; 7 | std::cout << "1: " << CopyCounter<1>::numCopies << " copies\n"; 8 | std::cout << "2: " << CopyCounter<2>::numCopies << " copies\n"; 9 | std::cout << "3: " << CopyCounter<3>::numCopies << " copies\n"; 10 | std::cout << "4: " << CopyCounter<4>::numCopies << " copies\n"; 11 | } 12 | -------------------------------------------------------------------------------- /meta/sqrt1.hpp: -------------------------------------------------------------------------------- 1 | // primary template to compute sqrt(N) 2 | template 3 | struct Sqrt { 4 | // compute the midpoint, rounded up 5 | static constexpr auto mid = (LO + HI + 1) / 2; 6 | 7 | // search a not too large value in a halved interval 8 | static constexpr auto value = 9 | (N < mid * mid) ? Sqrt::value : Sqrt::value; 10 | }; 11 | 12 | // partial specialization for the case when LO equals HI 13 | template 14 | struct Sqrt { 15 | static constexpr auto value = M; 16 | }; 17 | -------------------------------------------------------------------------------- /traits/isnothrowmoveconstructible2.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type, false_type, and bool_constant<> 2 | #include // for declval 3 | 4 | // primary template: 5 | template > 6 | struct IsNothrowMoveConstructibleT : std::false_type {}; 7 | 8 | // partial specialization (may be SFINAE'd away): 9 | template 10 | struct IsNothrowMoveConstructibleT()))>> 12 | : std::bool_constant()))> {}; 13 | -------------------------------------------------------------------------------- /details/definitions2.hpp: -------------------------------------------------------------------------------- 1 | class Collection { 2 | public: 3 | template // an in-class member class template definition 4 | class Node { 5 | //... 6 | }; 7 | 8 | template // an in-class (and therefore implicitly inline) 9 | T* alloc() { // member function template definition 10 | //... 11 | } 12 | 13 | template // a member variable template (since C++14) 14 | static T zero = 0; 15 | 16 | template // a member alias template 17 | using NodePtr = Node*; 18 | }; 19 | -------------------------------------------------------------------------------- /typelist/valuelisttest.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct GreaterThanT; 3 | 4 | template 5 | struct GreaterThanT, CTValue> { 6 | static constexpr bool value = First > Second; 7 | }; 8 | 9 | void valuelisttest() { 10 | using Integers = Valuelist; 11 | 12 | using SortedIntegers = InsertionSort; 13 | 14 | static_assert( 15 | std::is_same_v>, 16 | "insertion sort failed"); 17 | } 18 | -------------------------------------------------------------------------------- /variant/printrec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "variant-all.hpp" 3 | 4 | template 5 | void printImpl(V const& v) { 6 | if (v.template is()) { 7 | std::cout << v.template get(); 8 | } else if constexpr (sizeof...(Tail) > 0) { 9 | printImpl(v); 10 | } 11 | } 12 | 13 | template 14 | void print(Variant const& v) { 15 | printImpl, Types...>(v); 16 | } 17 | 18 | int main() { 19 | Variant v(1.5); 20 | print(v); 21 | } 22 | -------------------------------------------------------------------------------- /bridge/specificfunctorbridge.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class SpecificFunctorBridge : public FunctorBridge { 3 | Functor functor; 4 | 5 | public: 6 | template 7 | SpecificFunctorBridge(FunctorFwd&& functor) 8 | : functor(std::forward(functor)) {} 9 | virtual SpecificFunctorBridge* clone() const override { 10 | return new SpecificFunctorBridge(functor); 11 | } 12 | virtual R invoke(Args... args) const override { 13 | return functor(std::forward(args)...); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /bridge/forupto4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "functionptr.hpp" 4 | 5 | void forUpTo(int n, FunctionPtr f) { 6 | for (int i = 0; i != n; ++i) { 7 | f(i); // call passed function f for i 8 | } 9 | } 10 | 11 | void printInt(int i) { std::cout << i << ' '; } 12 | 13 | int main() { 14 | std::vector values; 15 | 16 | // insert values from 0 to 4: 17 | forUpTo(5, [&values](int i) { values.push_back(i); }); 18 | 19 | // print elements: 20 | forUpTo(5, 21 | printInt); // prints 0 1 2 3 4 22 | std::cout << '\n'; 23 | } 24 | -------------------------------------------------------------------------------- /exprtmpl/exprops1a.hpp: -------------------------------------------------------------------------------- 1 | // helper traits class to select how to refer to an expression template node 2 | // - in general by reference 3 | // - for scalars by value 4 | 5 | template 6 | class A_Scalar; 7 | 8 | // primary template 9 | template 10 | class A_Traits { 11 | public: 12 | using ExprRef = T const&; // type to refer to is constant reference 13 | }; 14 | 15 | // partial specialization for scalars 16 | template 17 | class A_Traits> { 18 | public: 19 | using ExprRef = A_Scalar; // type to refer to is ordinary value 20 | }; 21 | -------------------------------------------------------------------------------- /typelist/largesttype.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class LargestTypeT; 3 | 4 | // recursive case: 5 | template 6 | class LargestTypeT { 7 | private: 8 | using First = Front; 9 | using Rest = typename LargestTypeT>::Type; 10 | 11 | public: 12 | using Type = IfThenElse<(sizeof(First) >= sizeof(Rest)), First, Rest>; 13 | }; 14 | 15 | // basis case: 16 | template <> 17 | class LargestTypeT> { 18 | public: 19 | using Type = char; 20 | }; 21 | 22 | template 23 | using LargestType = typename LargestTypeT::Type; 24 | -------------------------------------------------------------------------------- /typelist/largesttypeacc.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class LargerTypeT : public IfThenElseT= sizeof(U), T, U> {}; 3 | 4 | template ::value> 5 | class LargestTypeAccT; 6 | 7 | template 8 | class LargestTypeAccT 9 | : public AccumulateT, LargerTypeT, Front> {}; 10 | 11 | template 12 | class LargestTypeAccT {}; 13 | 14 | template 15 | using LargestTypeAcc = typename LargestTypeAccT::Type; 16 | -------------------------------------------------------------------------------- /variant/findindexof.hpp: -------------------------------------------------------------------------------- 1 | template ::value> 3 | struct FindIndexOfT; 4 | 5 | // recursive case: 6 | template 7 | struct FindIndexOfT 8 | : public IfThenElse, T>::value, 9 | std::integral_constant, 10 | FindIndexOfT, T, N + 1>> {}; 11 | 12 | // basis case: 13 | template 14 | struct FindIndexOfT {}; 15 | -------------------------------------------------------------------------------- /details/tupleoverload.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class Tuple {}; 5 | 6 | template 7 | int f(Tuple) { 8 | return 1; 9 | } 10 | 11 | template 12 | int f(Tuple) { 13 | return 2; 14 | } 15 | 16 | template 17 | int f(Tuple) { 18 | return 3; 19 | } 20 | 21 | int main() { 22 | std::cout << f(Tuple()); // calls f<>(Tuple) 23 | std::cout << f(Tuple()); // calls f<>(Tuple) 24 | std::cout << f(Tuple()); // calls f<>(Tuple) 25 | } 26 | -------------------------------------------------------------------------------- /traits/isdefaultconstructible2.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct IsDefaultConstructibleHelper { 5 | private: 6 | // test() trying substitute call of a default constructor for T passed as U: 7 | template 8 | static std::true_type test(void*); 9 | // test() fallback: 10 | template 11 | static std::false_type test(...); 12 | 13 | public: 14 | using Type = decltype(test(nullptr)); 15 | }; 16 | 17 | template 18 | struct IsDefaultConstructibleT : IsDefaultConstructibleHelper::Type {}; 19 | -------------------------------------------------------------------------------- /traits/issame.cpp: -------------------------------------------------------------------------------- 1 | #include "issame.hpp" 2 | #include 3 | 4 | template 5 | void fooImpl(T, TrueType) { 6 | std::cout << "fooImpl(T,true) for int called\n"; 7 | } 8 | 9 | template 10 | void fooImpl(T, FalseType) { 11 | std::cout << "fooImpl(T,false) for other type called\n"; 12 | } 13 | 14 | template 15 | void foo(T t) { 16 | fooImpl(t, IsSameT{}); // choose impl. depending on whether T is int 17 | } 18 | 19 | int main() { 20 | foo(42); // calls \TfooImpl(42, TrueType{}) 21 | foo(7.7); // calls \TfooImpl(42, FalseType{}) 22 | } 23 | -------------------------------------------------------------------------------- /deduce/aliastemplate.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class Stack; 3 | 4 | template 5 | using DequeStack = Stack>; 6 | 7 | template 8 | void f1(Stack); 9 | 10 | template 11 | void f2(DequeStack); 12 | 13 | template 14 | void f3(Stack < T, std::deque); // equivalent to f2 15 | 16 | void test(DequeStack intStack) { 17 | f1(intStack); // OK: T deduced to int, Cont deduced to std::deque 18 | f2(intStack); // OK: T deduced to int 19 | f3(intStack); // OK: T deduced to int 20 | } 21 | -------------------------------------------------------------------------------- /meta/removeallextents.hpp: -------------------------------------------------------------------------------- 1 | // primary template: in general we yield the given type: 2 | template 3 | struct RemoveAllExtentsT { 4 | using Type = T; 5 | }; 6 | 7 | // partial specializations for array types (with and without bounds): 8 | template 9 | struct RemoveAllExtentsT { 10 | using Type = typename RemoveAllExtentsT::Type; 11 | }; 12 | template 13 | struct RemoveAllExtentsT { 14 | using Type = typename RemoveAllExtentsT::Type; 15 | }; 16 | 17 | template 18 | using RemoveAllExtents = typename RemoveAllExtentsT::Type; 19 | -------------------------------------------------------------------------------- /tuples/tupleio.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void printTuple(std::ostream& strm, Tuple<> const&, bool isFirst = true) { 4 | strm << (isFirst ? '(' : ')'); 5 | } 6 | 7 | template 8 | void printTuple(std::ostream& strm, Tuple const& t, 9 | bool isFirst = true) { 10 | strm << (isFirst ? "(" : ", "); 11 | strm << t.getHead(); 12 | printTuple(strm, t.getTail(), false); 13 | } 14 | 15 | template 16 | std::ostream& operator<<(std::ostream& strm, Tuple const& t) { 17 | printTuple(strm, t); 18 | return strm; 19 | } 20 | -------------------------------------------------------------------------------- /variant/variantvisitimpl.hpp: -------------------------------------------------------------------------------- 1 | template 3 | R variantVisitImpl(V&& variant, Visitor&& vis, Typelist) { 4 | if (variant.template is()) { 5 | return static_cast(std::forward(vis)( 6 | std::forward(variant).template get())); 7 | } else if constexpr (sizeof...(Tail) > 0) { 8 | return variantVisitImpl(std::forward(variant), 9 | std::forward(vis), Typelist()); 10 | } else { 11 | throw EmptyVariant(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /details/definitions1.hpp: -------------------------------------------------------------------------------- 1 | template // a namespace scope class template 2 | class Data { 3 | public: 4 | static constexpr bool copyable = true; 5 | //... 6 | }; 7 | 8 | template // a namespace scope function template 9 | void log(T x) { 10 | //... 11 | } 12 | 13 | template // a namespace scope variable template (since C++14) 14 | T zero = 0; 15 | 16 | template // a namespace scope variable template (since C++14) 17 | bool dataCopyable = Data::copyable; 18 | 19 | template // a namespace scope alias template 20 | using DataList = Data; 21 | -------------------------------------------------------------------------------- /details/tmplconstr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class C { 5 | public: 6 | C() = default; 7 | C(C const&) { std::cout << "copy constructor\n"; } 8 | C(C&&) { std::cout << "move constructor\n"; } 9 | template 10 | C(T&&) { 11 | std::cout << "template constructor\n"; 12 | } 13 | }; 14 | 15 | int main() { 16 | C x; 17 | C x2{x}; // prints: template constructor 18 | C x3{std::move(x)}; // prints: move constructor 19 | C const c; 20 | C x4{c}; // prints: copy constructor 21 | C x5{std::move(c)}; // prints: template constructor 22 | } 23 | -------------------------------------------------------------------------------- /tuples/tupleget.hpp: -------------------------------------------------------------------------------- 1 | // recursive case: 2 | template 3 | struct TupleGet { 4 | template 5 | static auto apply(Tuple const& t) { 6 | return TupleGet::apply(t.getTail()); 7 | } 8 | }; 9 | 10 | // basis case: 11 | template <> 12 | struct TupleGet<0> { 13 | template 14 | static Head const& apply(Tuple const& t) { 15 | return t.getHead(); 16 | } 17 | }; 18 | 19 | template 20 | auto get(Tuple const& t) { 21 | return TupleGet::apply(t); 22 | } 23 | -------------------------------------------------------------------------------- /typeoverload/iscontextualbool.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type and false_type 2 | #include // for declval() 3 | 4 | template 5 | class IsContextualBoolT { 6 | private: 7 | template 8 | struct Identity; 9 | template 10 | static std::true_type test(Identity() ? 0 : 1)>*); 11 | template 12 | static std::false_type test(...); 13 | 14 | public: 15 | static constexpr bool value = decltype(test(nullptr))::value; 16 | }; 17 | 18 | template 19 | constexpr bool IsContextualBool = IsContextualBoolT::value; 20 | -------------------------------------------------------------------------------- /variant/variantpromote.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "variant-all.hpp" 4 | 5 | int main() { 6 | Variant v1((short)123); 7 | 8 | Variant v2(v1); 9 | std::cout << "v2 contains the integer " << v2.get() << '\n'; 10 | 11 | v1 = 3.14f; 12 | Variant v3(std::move(v1)); 13 | std::cout << "v3 contains the double " << v3.get() << '\n'; 14 | 15 | v1 = "hello"; 16 | Variant v4(std::move(v1)); 17 | std::cout << "v4 contains the string " << v4.get() << '\n'; 18 | } 19 | -------------------------------------------------------------------------------- /basics/stack6decl.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Stack { 3 | private: 4 | std::deque elems; // elements 5 | 6 | public: 7 | void push(T const&); // push element 8 | void pop(); // pop element 9 | T const& top() const; // return top element 10 | bool empty() const { // return whether the stack is empty 11 | return elems.empty(); 12 | } 13 | 14 | // assign stack of elements of type T2 15 | template 16 | Stack& operator=(Stack const&); 17 | // to get access to private members of \TStack for any type T2: 18 | template 19 | friend class Stack; 20 | }; 21 | -------------------------------------------------------------------------------- /basics/stacknontype.cpp: -------------------------------------------------------------------------------- 1 | #include "stacknontype.hpp" 2 | #include 3 | #include 4 | 5 | int main() { 6 | Stack int20Stack; // stack of up to 20 ints 7 | Stack int40Stack; // stack of up to 40 ints 8 | Stack stringStack; // stack of up to 40 strings 9 | 10 | // manipulate stack of up to 20 ints 11 | int20Stack.push(7); 12 | std::cout << int20Stack.top() << '\n'; 13 | int20Stack.pop(); 14 | 15 | // manipulate stack of up to 40 strings 16 | stringStack.push("hello"); 17 | std::cout << stringStack.top() << '\n'; 18 | stringStack.pop(); 19 | } 20 | -------------------------------------------------------------------------------- /traits/hastype.cpp: -------------------------------------------------------------------------------- 1 | #include "hastype.hpp" 2 | 3 | #include 4 | #include 5 | 6 | DEFINE_HAS_TYPE(value_type); 7 | DEFINE_HAS_TYPE(char_type); 8 | 9 | int main() { 10 | std::cout << "int::value_type: " << HasTypeT_value_type::value << '\n'; 11 | std::cout << "std::vector::value_type: " 12 | << HasTypeT_value_type>::value << '\n'; 13 | std::cout << "std::iostream::value_type: " 14 | << HasTypeT_value_type::value << '\n'; 15 | std::cout << "std::iostream::char_type: " 16 | << HasTypeT_char_type::value << '\n'; 17 | } 18 | -------------------------------------------------------------------------------- /traits/rparam2.cpp: -------------------------------------------------------------------------------- 1 | #include "rparam.hpp" 2 | #include "rparamcls.hpp" 3 | 4 | // function that allows parameter passing by value or by reference 5 | template 6 | void foo_core(typename RParam::Type p1, typename RParam::Type p2) { 7 | //... 8 | } 9 | 10 | // wrapper to avoid explicit template parameter passing 11 | template 12 | void foo(T1&& p1, T2&& p2) { 13 | foo_core(std::forward(p1), std::forward(p2)); 14 | } 15 | 16 | int main() { 17 | MyClass1 mc1; 18 | MyClass2 mc2; 19 | foo(mc1, mc2); // same as foo_core(mc1,mc2) 20 | } 21 | -------------------------------------------------------------------------------- /meta/sqrt2.hpp: -------------------------------------------------------------------------------- 1 | #include "ifthenelse.hpp" 2 | 3 | // primary template for main recursive step 4 | template 5 | struct Sqrt { 6 | // compute the midpoint, rounded up 7 | static constexpr auto mid = (LO + HI + 1) / 2; 8 | 9 | // search a not too large value in a halved interval 10 | using SubT = 11 | IfThenElse<(N < mid * mid), Sqrt, Sqrt>; 12 | static constexpr auto value = SubT::value; 13 | }; 14 | 15 | // partial specialization for end of recursion criterion 16 | template 17 | struct Sqrt { 18 | static constexpr auto value = S; 19 | }; 20 | -------------------------------------------------------------------------------- /traits/accum1.cpp: -------------------------------------------------------------------------------- 1 | #include "accum1.hpp" 2 | #include 3 | 4 | int main() { 5 | // create array of 5 integer values 6 | int num[] = {1, 2, 3, 4, 5}; 7 | 8 | // print average value 9 | std::cout << "the average value of the integer values is " 10 | << accum(num, num + 5) / 5 << '\n'; 11 | 12 | // create array of character values 13 | char name[] = "templates"; 14 | int length = sizeof(name) - 1; 15 | 16 | // (try to) print average character value 17 | std::cout << "the average value of the characters in \"" << name << "\" is " 18 | << accum(name, name + length) / length << '\n'; 19 | } 20 | -------------------------------------------------------------------------------- /variant/variantchoiceinit.hpp: -------------------------------------------------------------------------------- 1 | #include // for std::move() 2 | 3 | template 4 | VariantChoice::VariantChoice(T const& value) { 5 | // place value in buffer and set type discriminator: 6 | new (getDerived().getRawBuffer()) T(value); 7 | getDerived().setDiscriminator(Discriminator); 8 | } 9 | 10 | template 11 | VariantChoice::VariantChoice(T&& value) { 12 | // place moved value in buffer and set type discriminator: 13 | new (getDerived().getRawBuffer()) T(std::move(value)); 14 | getDerived().setDiscriminator(Discriminator); 15 | } 16 | -------------------------------------------------------------------------------- /exprtmpl/exprops3.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class A_Subscript { 3 | public: 4 | // constructor initializes references to operands 5 | A_Subscript(A1 const& a, A2 const& b) : a1(a), a2(b) {} 6 | 7 | // process subscription when value requested 8 | decltype(auto) operator[](std::size_t idx) const { return a1[a2[idx]]; } 9 | T& operator[](std::size_t idx) { return a1[a2[idx]]; } 10 | 11 | // size is size of inner array 12 | std::size_t size() const { return a2.size(); } 13 | 14 | private: 15 | A1 const& a1; // reference to first operand 16 | A2 const& a2; // reference to second operand 17 | }; 18 | -------------------------------------------------------------------------------- /poly/printmax.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "MyClass.hpp" 6 | 7 | template 8 | void printMax(T const& coll) { 9 | // compute position of maximum value 10 | auto pos = std::max_element(coll.begin(), coll.end()); 11 | 12 | // print value of maximum element of coll (if any): 13 | if (pos != coll.end()) { 14 | std::cout << *pos << '\n'; 15 | } else { 16 | std::cout << "empty" << '\n'; 17 | } 18 | } 19 | 20 | int main() { 21 | std::vector c1; 22 | std::list c2; 23 | //... 24 | printMax(c1); 25 | printMax(c2); 26 | } 27 | -------------------------------------------------------------------------------- /utils/traits1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int i = 42; 6 | std::add_const::type c = i; // c is int const 7 | std::add_const_t c14 = i; // since C++14 8 | static_assert(std::is_const::value, "c should be const"); 9 | 10 | std::cout << std::boolalpha; 11 | std::cout << std::is_same::value // true 12 | << '\n'; 13 | std::cout << std::is_same_v // since C++17 14 | << '\n'; 15 | if (std::is_same{}) { // implicit conversion to bool 16 | std::cout << "same \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /inherit/objectcounter.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class ObjectCounter { 5 | private: 6 | inline static std::size_t count = 0; // number of existing objects 7 | 8 | protected: 9 | // default constructor 10 | ObjectCounter() { ++count; } 11 | 12 | // copy constructor 13 | ObjectCounter(ObjectCounter const &) { ++count; } 14 | 15 | // move constructor 16 | ObjectCounter(ObjectCounter &&) { ++count; } 17 | 18 | // destructor 19 | ~ObjectCounter() { --count; } 20 | 21 | public: 22 | // return number of existing objects: 23 | static std::size_t live() { return count; } 24 | }; 25 | -------------------------------------------------------------------------------- /traits/isfunction.hpp: -------------------------------------------------------------------------------- 1 | #include "../typelist/typelist.hpp" 2 | 3 | template 4 | struct IsFunctionT : std::false_type { // primary template: no function 5 | }; 6 | 7 | template 8 | struct IsFunctionT : std::true_type { // functions 9 | using Type = R; 10 | using ParamsT = Typelist; 11 | static constexpr bool variadic = false; 12 | }; 13 | 14 | template 15 | struct IsFunctionT : std::true_type { // variadic functions 16 | using Type = R; 17 | using ParamsT = Typelist; 18 | static constexpr bool variadic = true; 19 | }; 20 | -------------------------------------------------------------------------------- /typelist/genericlargesttype.hpp: -------------------------------------------------------------------------------- 1 | template ::value> 2 | class LargestTypeT; 3 | 4 | // recursive case: 5 | template 6 | class LargestTypeT { 7 | private: 8 | using Contender = Front; 9 | using Best = typename LargestTypeT>::Type; 10 | 11 | public: 12 | using Type = IfThenElse<(sizeof(Contender) >= sizeof(Best)), Contender, Best>; 13 | }; 14 | 15 | // basis case: 16 | template 17 | class LargestTypeT { 18 | public: 19 | using Type = char; 20 | }; 21 | 22 | template 23 | using LargestType = typename LargestTypeT::Type; 24 | -------------------------------------------------------------------------------- /basics/max2.cpp: -------------------------------------------------------------------------------- 1 | // maximum of two int values: 2 | int max(int a, int b) { return b < a ? a : b; } 3 | 4 | // maximum of two values of any type: 5 | template 6 | T max(T a, T b) { 7 | return b < a ? a : b; 8 | } 9 | 10 | int main() { 11 | ::max(7, 42); // calls the nontemplate for two ints 12 | ::max(7.0, 42.0); // calls max (by argument deduction) 13 | ::max('a', 'b'); // calls max (by argument deduction) 14 | ::max<>(7, 42); // calls max (by argument deduction) 15 | ::max(7, 42); // calls max (no argument deduction) 16 | ::max('a', 42.7); // calls the nontemplate for two ints 17 | } 18 | -------------------------------------------------------------------------------- /basics/specialmemtmpl2.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class Person { 6 | private: 7 | std::string name; 8 | 9 | public: 10 | // generic constructor for passed initial name: 11 | template 12 | explicit Person(STR&& n) : name(std::forward(n)) { 13 | std::cout << "TMPL-CONSTR for '" << name << "'\n"; 14 | } 15 | 16 | // copy and move constructor: 17 | Person(Person const& p) : name(p.name) { 18 | std::cout << "COPY-CONSTR Person '" << name << "'\n"; 19 | } 20 | Person(Person&& p) : name(std::move(p.name)) { 21 | std::cout << "MOVE-CONSTR Person '" << name << "'\n"; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /traits/decay.cpp: -------------------------------------------------------------------------------- 1 | #include "decay.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | void printDecayedType() { 8 | using A = typename DecayT::Type; 9 | std::cout << "Parameter type: " << typeid(A).name() << '\n'; 10 | std::cout << "- is int: " << std::is_same::value << '\n'; 11 | std::cout << "- is const: " << std::is_const::value << '\n'; 12 | std::cout << "- is pointer: " << std::is_pointer::value << '\n'; 13 | } 14 | 15 | int main() { 16 | printDecayedType(); 17 | printDecayedType(); 18 | printDecayedType(); 19 | printDecayedType(); 20 | } 21 | -------------------------------------------------------------------------------- /basics/errornovel2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Customer { 5 | private: 6 | std::string name; 7 | 8 | public: 9 | Customer(std::string const& n) : name(n) {} 10 | std::string getName() const { return name; } 11 | }; 12 | 13 | int main() { 14 | // provide our own hash function: 15 | struct MyCustomerHash { 16 | // NOTE: missing const is only an error with g++ and clang: 17 | std::size_t operator()(Customer const& c) { 18 | return std::hash()(c.getName()); 19 | } 20 | }; 21 | 22 | // and use it for a hash table of Customers: 23 | std::unordered_set coll; 24 | //... 25 | } 26 | -------------------------------------------------------------------------------- /typeoverload/container4.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Container { 3 | public: 4 | // construct from an input iterator sequence: 5 | template 6 | requires IsInputIterator Container(Iterator first, Iterator last); 7 | 8 | // construct from a random access iterator sequence: 9 | template 10 | requires IsRandomAccessIterator Container(Iterator first, 11 | Iterator last); 12 | 13 | // convert to a container so long as the value types are convertible: 14 | template 15 | requires IsConvertible operator Container() const; 16 | }; 17 | -------------------------------------------------------------------------------- /basics/max4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // maximum of two values of any type: 4 | template 5 | T max(T a, T b) { 6 | std::cout << "max() \n"; 7 | return b < a ? a : b; 8 | } 9 | 10 | // maximum of three values of any type: 11 | template 12 | T max(T a, T b, T c) { 13 | return max(max(a, b), c); // uses the template version even for ints 14 | } // because the following declaration comes 15 | // too late: 16 | // maximum of two int values: 17 | int max(int a, int b) { 18 | std::cout << "max(int,int) \n"; 19 | return b < a ? a : b; 20 | } 21 | 22 | int main() { 23 | ::max(47, 11, 33); // OOPS: uses max() instead of max(int,int) 24 | } 25 | -------------------------------------------------------------------------------- /basics/stack7decl.hpp: -------------------------------------------------------------------------------- 1 | template > 2 | class Stack { 3 | private: 4 | Cont elems; // elements 5 | 6 | public: 7 | void push(T const&); // push element 8 | void pop(); // pop element 9 | T const& top() const; // return top element 10 | bool empty() const { // return whether the stack is empty 11 | return elems.empty(); 12 | } 13 | 14 | // assign stack of elements of type T2 15 | template 16 | Stack& operator=(Stack const&); 17 | // to get access to private members of Stack for any type T2: 18 | template 19 | friend class Stack; 20 | }; 21 | -------------------------------------------------------------------------------- /overload/initlistctor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | struct Array { 7 | Array(std::initializer_list) { std::cout << "#1\n"; } 8 | Array(unsigned n, T const&) { std::cout << "#2\n"; } 9 | }; 10 | 11 | void arr1(Array) {} 12 | 13 | void arr2(Array) {} 14 | 15 | int main() { 16 | arr1({1, 2, 3, 4, 5}); // prints \#1 17 | arr1({1, 2}); // prints \#1 18 | arr1({10u, 5}); // prints \#1 19 | arr2({"hello", "initializer", "list"}); // prints \#1 20 | arr2({10, "hello"}); // prints \#2 21 | } 22 | -------------------------------------------------------------------------------- /meta/ifthenelse.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IFTHENELSE_HPP 2 | #define IFTHENELSE_HPP 3 | 4 | // primary template: yield second or third argument depending on first argument 5 | template 6 | struct IfThenElseT; 7 | 8 | // partial specialization: true yields second argument 9 | template 10 | struct IfThenElseT { 11 | using Type = TrueType; 12 | }; 13 | 14 | // partial specialization: false yields third argument 15 | template 16 | struct IfThenElseT { 17 | using Type = FalseType; 18 | }; 19 | 20 | #endif // IFTHENELSE_HPP 21 | -------------------------------------------------------------------------------- /traits/passbyvalue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | void f(T) {} 7 | 8 | template 9 | void printParameterType(void (*)(A)) { 10 | std::cout << "Parameter type: " << typeid(A).name() << '\n'; 11 | std::cout << "- is int: " << std::is_same::value << '\n'; 12 | std::cout << "- is const: " << std::is_const::value << '\n'; 13 | std::cout << "- is pointer: " << std::is_pointer::value << '\n'; 14 | } 15 | 16 | int main() { 17 | printParameterType(&f); 18 | printParameterType(&f); 19 | printParameterType(&f); 20 | printParameterType(&f); 21 | } 22 | -------------------------------------------------------------------------------- /meta/durationadd.hpp: -------------------------------------------------------------------------------- 1 | // adding two durations where unit type might differ: 2 | template 3 | auto constexpr operator+(Duration const& lhs, 4 | Duration const& rhs) { 5 | // resulting type is a unit with 1 a nominator and 6 | // the resulting denominator of adding both unit type fractions 7 | using VT = Ratio<1, RatioAdd::den>; 8 | // resulting value is the sum of both values 9 | // converted to the resulting unit type: 10 | auto val = lhs.value() * VT::den / U1::den * U1::num + 11 | rhs.value() * VT::den / U2::den * U2::num; 12 | return Duration(val); 13 | } 14 | -------------------------------------------------------------------------------- /inherit/basememberpair.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BASE_MEMBER_PAIR_HPP 2 | #define BASE_MEMBER_PAIR_HPP 3 | 4 | template 5 | class BaseMemberPair : private Base { 6 | private: 7 | Member mem; 8 | 9 | public: 10 | // constructor 11 | BaseMemberPair(Base const& b, Member const& m) : Base(b), mem(m) {} 12 | 13 | // access base class data via first() 14 | Base const& base() const { return static_cast(*this); } 15 | Base& base() { return static_cast(*this); } 16 | 17 | // access member data via second() 18 | Member const& member() const { return this->mem; } 19 | Member& member() { return this->mem; } 20 | }; 21 | 22 | #endif // BASE_MEMBER_PAIR_HPP 23 | -------------------------------------------------------------------------------- /tuples/tuple0.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Tuple; 3 | 4 | // recursive case: 5 | template 6 | class Tuple { 7 | private: 8 | Head head; 9 | Tuple tail; 10 | 11 | public: 12 | // constructors: 13 | Tuple() {} 14 | Tuple(Head const& head, Tuple const& tail) 15 | : head(head), tail(tail) {} 16 | //... 17 | 18 | Head& getHead() { return head; } 19 | Head const& getHead() const { return head; } 20 | Tuple& getTail() { return tail; } 21 | Tuple const& getTail() const { return tail; } 22 | }; 23 | 24 | // basis case: 25 | template <> 26 | class Tuple<> { 27 | // no storage required 28 | }; 29 | -------------------------------------------------------------------------------- /basics/stackauto.cpp: -------------------------------------------------------------------------------- 1 | #include "stackauto.hpp" 2 | #include 3 | #include 4 | 5 | int main() { 6 | Stack int20Stack; // stack of up to 20 ints 7 | Stack stringStack; // stack of up to 40 strings 8 | 9 | // manipulate stack of up to 20 ints 10 | int20Stack.push(7); 11 | std::cout << int20Stack.top() << '\n'; 12 | auto size1 = int20Stack.size(); 13 | 14 | // manipulate stack of up to 40 strings 15 | stringStack.push("hello"); 16 | std::cout << stringStack.top() << '\n'; 17 | auto size2 = stringStack.size(); 18 | 19 | if (!std::is_same_v) { 20 | std::cout << "size types differ" << '\n'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /variant/variantvisitresultcommon.hpp: -------------------------------------------------------------------------------- 1 | #include "accumulate.hpp" 2 | #include "commontype.hpp" 3 | 4 | // the result type produced when calling a visitor with a value of type T: 5 | template 6 | using VisitElementResult = decltype(declval()(declval())); 7 | 8 | // the common result type for a visitor called with each of the given element 9 | // types: 10 | template 11 | class VisitResultT { 12 | using ResultTypes = Typelist...>; 13 | 14 | public: 15 | using Type = 16 | Accumulate, CommonTypeT, Front>; 17 | }; 18 | -------------------------------------------------------------------------------- /basics/invokeret.hpp: -------------------------------------------------------------------------------- 1 | #include // for std::forward() 2 | #include // for std::is_same<> and invoke_result<> 3 | #include // for std::invoke() 4 | 5 | template 6 | decltype(auto) call(Callable&& op, Args&&... args) { 7 | if constexpr (std::is_same_v, void>) { 8 | // return type is void: 9 | std::invoke(std::forward(op), std::forward(args)...); 10 | //... 11 | return; 12 | } else { 13 | // return type is not void: 14 | decltype(auto) ret{ 15 | std::invoke(std::forward(op), std::forward(args)...)}; 16 | //... 17 | return ret; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /typeoverload/isconvertible.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct IsConvertibleT { 5 | private: 6 | // to check whether we can call this helper func for a FROM object: 7 | static void func(TO); 8 | // test() trying to call the helper func(): 9 | template ()))> 11 | static char test(void*); 12 | // test() fallback: 13 | template 14 | static long test(...); 15 | 16 | public: 17 | static constexpr bool value = sizeof(test(nullptr)) == 1; 18 | }; 19 | 20 | template 21 | constexpr bool IsConvertible = IsConvertibleT::value; 22 | -------------------------------------------------------------------------------- /traits/elementtype.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct ElementT; // primary template 6 | 7 | template 8 | struct ElementT> { // partial specialization for std::vector 9 | using Type = T; 10 | }; 11 | 12 | template 13 | struct ElementT> { // partial specialization for std::list 14 | using Type = T; 15 | }; 16 | //... 17 | 18 | template 19 | struct ElementT { // partial specialization for arrays of known bounds 20 | using Type = T; 21 | }; 22 | 23 | template 24 | struct ElementT { // partial specialization for arrays of unknown bounds 25 | using Type = T; 26 | }; 27 | //... 28 | -------------------------------------------------------------------------------- /tuples/tuplestorage3.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Tuple; 3 | 4 | // recursive case: 5 | template 6 | class Tuple : private TupleElt, 7 | private Tuple { 8 | using HeadElt = TupleElt; 9 | 10 | public: 11 | Head& getHead() { return static_cast(this)->get(); } 12 | Head const& getHead() const { 13 | return static_cast(this)->get(); 14 | } 15 | Tuple& getTail() { return *this; } 16 | Tuple const& getTail() const { return *this; } 17 | }; 18 | 19 | // basis case: 20 | template <> 21 | class Tuple<> { 22 | // no storage required 23 | }; 24 | -------------------------------------------------------------------------------- /bridge/isequalitycomparable.hpp: -------------------------------------------------------------------------------- 1 | #include // for true_type and false_type 2 | #include // for declval() 3 | 4 | template 5 | class IsEqualityComparable { 6 | private: 7 | // test convertibility of == and ! == to bool: 8 | static void* conv(bool); // to check convertibility to bool 9 | template 10 | static std::true_type test( 11 | decltype(conv(std::declval() == std::declval())), 12 | decltype(conv(!(std::declval() == std::declval())))); 13 | // fallback: 14 | template 15 | static std::false_type test(...); 16 | 17 | public: 18 | static constexpr bool value = decltype(test(nullptr, nullptr))::value; 19 | }; 20 | -------------------------------------------------------------------------------- /traits/ifthenelse.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IFTHENELSE_HPP 2 | #define IFTHENELSE_HPP 3 | 4 | // primary template: yield the second argument by default and rely on 5 | // a partial specialization to yield the third argument 6 | // if COND is false 7 | template 8 | struct IfThenElseT { 9 | using Type = TrueType; 10 | }; 11 | 12 | // partial specialization: false yields third argument 13 | template 14 | struct IfThenElseT { 15 | using Type = FalseType; 16 | }; 17 | 18 | template 19 | using IfThenElse = typename IfThenElseT::Type; 20 | #endif // IFTHENELSE_HPP 21 | -------------------------------------------------------------------------------- /typelist/accumulate.hpp: -------------------------------------------------------------------------------- 1 | template class F, typename I, 2 | bool = IsEmpty::value> 3 | class AccumulateT; 4 | 5 | // recursive case: 6 | template class F, typename I> 7 | class AccumulateT 8 | : public AccumulateT, F, typename F>::Type> { 9 | }; 10 | 11 | // basis case: 12 | template class F, typename I> 13 | class AccumulateT { 14 | public: 15 | using Type = I; 16 | }; 17 | 18 | template class F, typename I> 19 | using Accumulate = typename AccumulateT::Type; 20 | -------------------------------------------------------------------------------- /typelist/transform.hpp: -------------------------------------------------------------------------------- 1 | template class MetaFun, 2 | bool Empty = IsEmpty::value> 3 | class TransformT; 4 | 5 | // recursive case: 6 | template class MetaFun> 7 | class TransformT 8 | : public PushFrontT, MetaFun>::Type, 9 | typename MetaFun>::Type> {}; 10 | 11 | // basis case: 12 | template class MetaFun> 13 | class TransformT { 14 | public: 15 | using Type = List; 16 | }; 17 | 18 | template class MetaFun> 19 | using Transform = typename TransformT::Type; 20 | -------------------------------------------------------------------------------- /typeoverload/container1.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "enableif.hpp" 3 | #include "isconvertible.hpp" 4 | 5 | template 6 | constexpr bool IsInputIterator = 7 | IsConvertible::iterator_category, 8 | std::input_iterator_tag>; 9 | 10 | template 11 | class Container { 12 | public: 13 | // construct from an input iterator sequence: 14 | template >> 15 | Container(Iterator first, Iterator last); 16 | 17 | // convert to a container so long as the value types are convertible: 18 | template >> 19 | operator Container() const; 20 | }; 21 | -------------------------------------------------------------------------------- /variant/accumulate.hpp: -------------------------------------------------------------------------------- 1 | template class F, typename I, 2 | bool = IsEmpty::value> 3 | class AccumulateT; 4 | 5 | // recursive case: 6 | template class F, typename I> 7 | class AccumulateT 8 | : public AccumulateT, F, typename F>::Type> { 9 | }; 10 | 11 | // basis case: 12 | template class F, typename I> 13 | class AccumulateT { 14 | public: 15 | using Type = I; 16 | }; 17 | 18 | template class F, typename I> 19 | using Accumulate = typename AccumulateT::Type; 20 | -------------------------------------------------------------------------------- /basics/foldtraverse.cpp: -------------------------------------------------------------------------------- 1 | // define binary tree structure and traverse helpers: 2 | struct Node { 3 | int value; 4 | Node* left; 5 | Node* right; 6 | Node(int i = 0) : value(i), left(nullptr), right(nullptr) {} 7 | //... 8 | }; 9 | auto left = &Node::left; 10 | auto right = &Node::right; 11 | 12 | // traverse tree, using fold expression: 13 | template 14 | Node* traverse(T np, TP... paths) { 15 | return (np->*...->*paths); // np ->* paths1 ->* paths2 ... 16 | } 17 | 18 | int main() { 19 | // init binary tree structure: 20 | Node* root = new Node{0}; 21 | root->left = new Node{1}; 22 | root->left->right = new Node{2}; 23 | //... 24 | // traverse binary tree: 25 | Node* node = traverse(root, left, right); 26 | //... 27 | } 28 | -------------------------------------------------------------------------------- /inherit/virtual.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class NotVirtual {}; 4 | 5 | class Virtual { 6 | public: 7 | virtual void foo() {} 8 | }; 9 | 10 | template 11 | class Base : public Mixins... { 12 | public: 13 | // the virtuality of foo() depends on its declaration 14 | // (if any) in the base classes Mixins... 15 | void foo() { std::cout << "Base::foo()" << '\n'; } 16 | }; 17 | 18 | template 19 | class Derived : public Base { 20 | public: 21 | void foo() { std::cout << "Derived::foo()" << '\n'; } 22 | }; 23 | 24 | int main() { 25 | Base* p1 = new Derived; 26 | p1->foo(); // calls Base::foo() 27 | 28 | Base* p2 = new Derived; 29 | p2->foo(); // calls Derived::foo() 30 | } 31 | -------------------------------------------------------------------------------- /traits/smallestint.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ifthenelse.hpp" 3 | 4 | template 5 | struct SmallestIntT { 6 | using Type = typename IfThenElseT< 7 | N <= std::numeric_limits::max(), char, 8 | typename IfThenElseT< 9 | N <= std::numeric_limits::max(), short, 10 | typename IfThenElseT< 11 | N <= std::numeric_limits::max(), int, 12 | typename IfThenElseT< 13 | N <= std::numeric_limits::max(), long, 14 | typename IfThenElseT< 15 | N <= std::numeric_limits::max(), 16 | long long, // then 17 | void // fallback 18 | >::Type>::Type>::Type>::Type>::Type; 19 | }; 20 | -------------------------------------------------------------------------------- /exprtmpl/sarrayops2.hpp: -------------------------------------------------------------------------------- 1 | // additive assignment of SArray 2 | template 3 | SArray& SArray::operator+=(SArray const& b) { 4 | assert(size() == orig.size()); 5 | for (std::size_t k = 0; k < size(); ++k) { 6 | (*this)[k] += b[k]; 7 | } 8 | return *this; 9 | } 10 | 11 | // multiplicative assignment of SArray 12 | template 13 | SArray& SArray::operator*=(SArray const& b) { 14 | assert(size() == orig.size()); 15 | for (std::size_t k = 0; k < size(); ++k) { 16 | (*this)[k] *= b[k]; 17 | } 18 | return *this; 19 | } 20 | 21 | // multiplicative assignment of scalar 22 | template 23 | SArray& SArray::operator*=(T const& s) { 24 | for (std::size_t k = 0; k < size(); ++k) { 25 | (*this)[k] *= s; 26 | } 27 | return *this; 28 | } 29 | -------------------------------------------------------------------------------- /meta/sqrtconstexpr.hpp: -------------------------------------------------------------------------------- 1 | template 2 | constexpr T sqrt(T x) { 3 | // handle cases where x and its square root are equal as a special case to 4 | // simplify the iteration criterion for larger x: 5 | if (x <= 1) { 6 | return x; 7 | } 8 | 9 | // repeatedly determine in which half of a $[$lo, hi$]$ interval the square 10 | // root of x is located, until the interval is reduced to just one value: 11 | T lo = 0, hi = x; 12 | for (;;) { 13 | auto mid = (hi + lo) / 2, midSquared = mid * mid; 14 | if (lo + 1 >= hi || midSquared == x) { 15 | // mid must be the square root: 16 | return mid; 17 | } 18 | // continue with the higher/lower half-interval: 19 | if (midSquared < x) { 20 | lo = mid; 21 | } else { 22 | hi = mid; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /traits/accumtraits4.hpp: -------------------------------------------------------------------------------- 1 | template 2 | struct AccumulationTraits; 3 | 4 | template <> 5 | struct AccumulationTraits { 6 | using AccT = int; 7 | static constexpr AccT zero() { return 0; } 8 | }; 9 | 10 | template <> 11 | struct AccumulationTraits { 12 | using AccT = int; 13 | static constexpr AccT zero() { return 0; } 14 | }; 15 | 16 | template <> 17 | struct AccumulationTraits { 18 | using AccT = long; 19 | static constexpr AccT zero() { return 0; } 20 | }; 21 | 22 | template <> 23 | struct AccumulationTraits { 24 | using AccT = unsigned long; 25 | static constexpr AccT zero() { return 0; } 26 | }; 27 | 28 | template <> 29 | struct AccumulationTraits { 30 | using AccT = double; 31 | static constexpr AccT zero() { return 0; } 32 | }; 33 | //... 34 | -------------------------------------------------------------------------------- /basics/max3ref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // maximum of two values of any type (call-by-reference) 4 | template 5 | T const& max(T const& a, T const& b) { 6 | return b < a ? a : b; 7 | } 8 | 9 | // maximum of two C-strings (call-by-value) 10 | char const* max(char const* a, char const* b) { 11 | return std::strcmp(b, a) < 0 ? a : b; 12 | } 13 | 14 | // maximum of three values of any type (call-by-reference) 15 | template 16 | T const& max(T const& a, T const& b, T const& c) { 17 | return max(max(a, b), c); // error if max(a,b) uses call-by-value 18 | } 19 | 20 | int main() { 21 | auto m1 = ::max(7, 42, 68); // OK 22 | 23 | char const* s1 = "frederic"; 24 | char const* s2 = "anica"; 25 | char const* s3 = "lucas"; 26 | auto m2 = ::max(s1, s2, s3); // run-time ERROR 27 | } 28 | -------------------------------------------------------------------------------- /variant/variantstorage.hpp: -------------------------------------------------------------------------------- 1 | #include // for std::launder() 2 | 3 | template 4 | class VariantStorage { 5 | using LargestT = LargestType>; 6 | alignas(Types...) unsigned char buffer[sizeof(LargestT)]; 7 | unsigned char discriminator = 0; 8 | 9 | public: 10 | unsigned char getDiscriminator() const { return discriminator; } 11 | void setDiscriminator(unsigned char d) { discriminator = d; } 12 | 13 | void* getRawBuffer() { return buffer; } 14 | const void* getRawBuffer() const { return buffer; } 15 | 16 | template 17 | T* getBufferAs() { 18 | return std::launder(reinterpret_cast(buffer)); 19 | } 20 | template 21 | T const* getBufferAs() const { 22 | return std::launder(reinterpret_cast(buffer)); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /tuples/tupleelt2.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template ::value && !std::is_final::value> 5 | class TupleElt; 6 | 7 | template 8 | class TupleElt { 9 | T value; 10 | 11 | public: 12 | TupleElt() = default; 13 | template 14 | TupleElt(U&& other) : value(std::forward(other)) {} 15 | 16 | T& get() { return value; } 17 | T const& get() const { return value; } 18 | }; 19 | 20 | template 21 | class TupleElt : private T { 22 | public: 23 | TupleElt() = default; 24 | template 25 | TupleElt(U&& other) : T(std::forward(other)) {} 26 | 27 | T& get() { return *this; } 28 | T const& get() const { return *this; } 29 | }; 30 | -------------------------------------------------------------------------------- /tuples/tuplesort.hpp: -------------------------------------------------------------------------------- 1 | // metafunction wrapper that compares the elements in a tuple: 2 | template class F> 3 | class MetafunOfNthElementT { 4 | public: 5 | template 6 | class Apply; 7 | 8 | template 9 | class Apply, CTValue> 10 | : public F, NthElement> {}; 11 | }; 12 | 13 | // sort a tuple based on comparing the element types: 14 | template