|
@@ -0,0 +1,705 @@
|
|
|
+#include "stdafx.h"
|
|
|
+#include <vector>
|
|
|
+
|
|
|
+#define WRONG_CODE_ENABLED 0
|
|
|
+
|
|
|
+
|
|
|
+namespace _0
|
|
|
+{
|
|
|
+ template <typename T>
|
|
|
+ class ClassA
|
|
|
+ {
|
|
|
+ T a;
|
|
|
+ T* b;
|
|
|
+ T foo();
|
|
|
+ void foo2(T const&);
|
|
|
+ };
|
|
|
+
|
|
|
+ template <int Sz>
|
|
|
+ class ClassB
|
|
|
+ {
|
|
|
+ int arr[Sz];
|
|
|
+ };
|
|
|
+
|
|
|
+ size_t a = sizeof(ClassB<3>);
|
|
|
+ size_t b = sizeof(ClassB<7>);
|
|
|
+
|
|
|
+ template <typename T> void FunctionA(T const& param)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T> T FunctionB()
|
|
|
+ {
|
|
|
+ return T();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _1_1
|
|
|
+{
|
|
|
+ template <typename T>
|
|
|
+ class ClassA
|
|
|
+ {
|
|
|
+ T a;
|
|
|
+ T* b;
|
|
|
+ T foo();
|
|
|
+ template <typename U> void foo2(T const&, U const&);
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _1_2
|
|
|
+{
|
|
|
+ _1_1::ClassA<int> a;
|
|
|
+
|
|
|
+ #if WRONG_CODE_ENABLED
|
|
|
+ _1_1::ClassA<WhatTheFuck> b;
|
|
|
+ _1_1::ClassA c;
|
|
|
+ #endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _1_3
|
|
|
+{
|
|
|
+ template <typename T>
|
|
|
+ class ClassB
|
|
|
+ {
|
|
|
+ T* a;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class ClassC
|
|
|
+ {
|
|
|
+ T a;
|
|
|
+ };
|
|
|
+
|
|
|
+ struct StructA;
|
|
|
+ ClassB<StructA> d;
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ ClassC<StructA> e;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _1_4
|
|
|
+{
|
|
|
+
|
|
|
+ template <typename T> class ClassD
|
|
|
+ {
|
|
|
+ int a;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ template <> class ClassD<int> // 1. template <> 2. ClassD<int>
|
|
|
+ {
|
|
|
+ int b;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <> class ClassD<float>
|
|
|
+ {
|
|
|
+ int c;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T> class ClassD<T*> // 1. template <typename T> 2. ClassD<T*>
|
|
|
+ {
|
|
|
+ int d;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <> class ClassD<int*> // 1. template <> 2. ClassD<T*>
|
|
|
+ {
|
|
|
+ int e;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T, typename U> class ClassE
|
|
|
+ {
|
|
|
+ int a;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T, typename U> class ClassE<T, U*>
|
|
|
+ {
|
|
|
+ int b;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T> class ClassE<T, int>
|
|
|
+ {
|
|
|
+ int c;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T> class ClassE<T, int*>
|
|
|
+ {
|
|
|
+ int d;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename U> class ClassE<int, U>
|
|
|
+ {
|
|
|
+ int e;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <> class ClassE<int, int>
|
|
|
+ {
|
|
|
+ int f;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _2_1
|
|
|
+{
|
|
|
+
|
|
|
+ template <typename T> void foo(T const& x) {}
|
|
|
+ template <typename T> void foo(T& y) {}
|
|
|
+ void foo(int&) {}
|
|
|
+ void foo(int) {}
|
|
|
+
|
|
|
+
|
|
|
+ template <> void foo<bool>(bool const& x) {}
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T> void foo(T const*) {}
|
|
|
+
|
|
|
+ template <typename T, typename U> void foo2(T const&, U const&);
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ template <typename U> void foo2<int, U>(int const&, U const&);
|
|
|
+ template <typename T, typename U> void foo2<T, U>(int const&, U const&);
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+ template <typename U> void foo2(int const&, U const&);
|
|
|
+ template <typename T, typename U> void foo2(T const*, U const&);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <typename UninferableT, typename InferableT>
|
|
|
+ UninferableT foo3(InferableT const&) { return UninferableT(); }
|
|
|
+
|
|
|
+ void test()
|
|
|
+ {
|
|
|
+
|
|
|
+ int x = 5;
|
|
|
+ float y = 10.0f;
|
|
|
+ foo(y);
|
|
|
+ int const z = 5;
|
|
|
+ foo(z);
|
|
|
+ foo(true);
|
|
|
+ foo3<int>(0.0f);
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ foo(3);
|
|
|
+ foo(x);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _2_2
|
|
|
+{
|
|
|
+ template <typename T>
|
|
|
+ class ClassA
|
|
|
+ {
|
|
|
+ T x;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class ClassB
|
|
|
+ {
|
|
|
+ T* x;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class ClassC: public ClassB<T>
|
|
|
+ {
|
|
|
+ T* x;
|
|
|
+ };
|
|
|
+
|
|
|
+ ClassC<int> a;
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ class ClassC: public ClassA<ClassC>
|
|
|
+ {
|
|
|
+ };
|
|
|
+#endif
|
|
|
+
|
|
|
+ class ClassD: public ClassB<ClassD>
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _3_1
|
|
|
+{
|
|
|
+ bool equal(int a, int b)
|
|
|
+ {
|
|
|
+ return a == b;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T, typename U>
|
|
|
+ class Equal
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static bool const value = false;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class Equal<T, T>
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static bool const value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ bool x = Equal<int, float>::value;
|
|
|
+ bool y = Equal<int, int>::value;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _3_2
|
|
|
+{
|
|
|
+ class ClassA
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+ template <int Sz> struct Mark
|
|
|
+ {
|
|
|
+ char _[Sz];
|
|
|
+ };
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ template <typename T>
|
|
|
+ Mark<1> TestIncrementAdd(T const& v)
|
|
|
+ {
|
|
|
+ T tmp = v;
|
|
|
+ ++tmp;
|
|
|
+ return Mark<1>();
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ Mark<2> TestIncrementAdd(T const& v)
|
|
|
+ {
|
|
|
+ return Mark<2>();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool a = TestIncrementAdd( ClassA() ) ) == sizeof(Mark<1>);
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+ class ClassB
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef int Marker;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T> void test(typename T::Marker) { }
|
|
|
+ template <typename T> void test(T) { }
|
|
|
+
|
|
|
+ void DoTest()
|
|
|
+ {
|
|
|
+ test<ClassB>(10);
|
|
|
+ test<int>(10);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _3_3
|
|
|
+{
|
|
|
+ template <typename T, typename U> class is_same;
|
|
|
+
|
|
|
+
|
|
|
+ template <typename B, typename D> class is_base_of;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ typedef char Accepted;
|
|
|
+ typedef int Rejected;
|
|
|
+
|
|
|
+ class B
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+ class D: public B
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+ class D2: public D
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class is_class
|
|
|
+ {
|
|
|
+ private:
|
|
|
+
|
|
|
+ template <typename U> static Accepted test( int U::* );
|
|
|
+ template <typename U> static Rejected test(...);
|
|
|
+
|
|
|
+ public:
|
|
|
+ static const bool value = sizeof( test<T>(0) ) == sizeof(Accepted);
|
|
|
+ };
|
|
|
+
|
|
|
+ bool a = is_class<int>::value;
|
|
|
+ bool b = is_class<B>::value;
|
|
|
+
|
|
|
+
|
|
|
+ template <typename Source, typename Dest>
|
|
|
+ class Convertible
|
|
|
+ {
|
|
|
+ private:
|
|
|
+
|
|
|
+ static Accepted test(Dest*);
|
|
|
+ static Rejected test(...);
|
|
|
+ public:
|
|
|
+ static const bool value = sizeof( test(static_cast<Source*>(NULL)) ) == sizeof(Accepted);
|
|
|
+ };
|
|
|
+
|
|
|
+ bool c = Convertible<B, D>::value;
|
|
|
+ bool d = Convertible<D, B>::value;
|
|
|
+ bool e = Convertible<B, int>::value;
|
|
|
+
|
|
|
+
|
|
|
+ using _3_1::Equal;
|
|
|
+
|
|
|
+ template <typename Base, typename Derived>
|
|
|
+ class is_base_of
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static bool const value =
|
|
|
+ is_class<Base>::value &&
|
|
|
+ is_class<Derived>::value &&
|
|
|
+ Convertible<Base, Derived>::value &&
|
|
|
+ !Equal<Base, Derived>::value;
|
|
|
+ };
|
|
|
+
|
|
|
+ bool f = is_base_of<B, D2>::value;
|
|
|
+ bool g = is_base_of<D2, D>::value;
|
|
|
+ bool h = is_base_of<B, int>::value;
|
|
|
+ bool i = is_base_of<float, int>::value;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _3_4
|
|
|
+{
|
|
|
+
|
|
|
+ int basic_algo(int a, int b)
|
|
|
+ {
|
|
|
+ int result = 0;
|
|
|
+ for (int i = a; i <= b; ++i)
|
|
|
+ {
|
|
|
+ result += i;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ int recursive_algo(int a, int b)
|
|
|
+ {
|
|
|
+ if (a == b)
|
|
|
+ {
|
|
|
+ return b;
|
|
|
+ }
|
|
|
+ return a + recursive_algo(a+1, b);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ template <int a, int b>
|
|
|
+ class MetaSum
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = MetaSum<a+1, b>::value + a;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <int a>
|
|
|
+ class MetaSum<a, a>
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = a;
|
|
|
+ };
|
|
|
+
|
|
|
+ int a = MetaSum<1, 10>::value;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _3_5
|
|
|
+{
|
|
|
+ template <int Index>
|
|
|
+ class Fibonacci
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = Fibonacci<Index - 1>::value + Fibonacci<Index - 2>::value;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <>
|
|
|
+ class Fibonacci<0>
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = 0;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <>
|
|
|
+ class Fibonacci<1>
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = 1;
|
|
|
+ };
|
|
|
+
|
|
|
+ int a = Fibonacci<8>::value;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _4
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ class ClassA
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef int NestedType;
|
|
|
+ };
|
|
|
+
|
|
|
+ class ClassB
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef ClassA::NestedType NestedType;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class ClassC
|
|
|
+ {
|
|
|
+ public:
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ typedef T::NestedType NestedType;
|
|
|
+#endif
|
|
|
+ typedef typename T::NestedType NestedType;
|
|
|
+ typedef typename std::vector<T>::iterator iterator;
|
|
|
+ };
|
|
|
+
|
|
|
+ class ClassD
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ template <typename U, typename V> class NestedType;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ class ClassE
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ template <typename U> class NestedType;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T, typename U>
|
|
|
+ class ClassF
|
|
|
+ {
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+ typedef typename T::NestedType<U> NestedType;
|
|
|
+#endif
|
|
|
+ typedef typename T::template NestedType<U, int> NestedType;
|
|
|
+ typedef typename ClassE<T>::template NestedType<U> NestedType2;
|
|
|
+ };
|
|
|
+
|
|
|
+ ClassC<ClassB> a;
|
|
|
+ ClassF<ClassD, float> b;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _5_1
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <int i>
|
|
|
+ class int_
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static int const value = i;
|
|
|
+ };
|
|
|
+
|
|
|
+ int a = int_<5>::value;
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ void Do(T* obj, int_<2>)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ void Do(T* obj, int_<1>)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ void foo()
|
|
|
+ {
|
|
|
+ Do( static_cast<int*>(nullptr), int_<1>() );
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T, int i> void DoAnotherWay(T* obj)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ template <bool v>
|
|
|
+ class bool_
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ static bool const value = v;
|
|
|
+ };
|
|
|
+
|
|
|
+ typedef bool_<true> true_;
|
|
|
+ typedef bool_<false> false_;
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+
|
|
|
+ template <typename T> void DoAnotherWay<T, 1>(T* obj) {}
|
|
|
+ template <typename T> void DoAnotherWay<T, 2>(T* obj) {}
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T, typename U>
|
|
|
+ class add_
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef int_<T::value + U::value> type;
|
|
|
+ static int const value = type::value;
|
|
|
+ };
|
|
|
+
|
|
|
+#if WRONG_CODE_ENABLED
|
|
|
+
|
|
|
+ template <int x, int y>
|
|
|
+ class add_
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef int_<x+y> type;
|
|
|
+ static int const value = type::value;
|
|
|
+ };
|
|
|
+#endif
|
|
|
+ template <int x, int y>
|
|
|
+ class add_c
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ typedef int_<x+y> type;
|
|
|
+ static int const value = type::value;
|
|
|
+ };
|
|
|
+
|
|
|
+ typedef add_< int_<2>, int_<3> >::type sum;
|
|
|
+ int b = sum::value;
|
|
|
+
|
|
|
+ typedef add_< int_<2>, int_<3> >::type sum_c;
|
|
|
+ int c = sum_c::value;
|
|
|
+
|
|
|
+
|
|
|
+ template <typename T, typename U>
|
|
|
+ class add2_: public int_<T::value+U::value>
|
|
|
+ {
|
|
|
+ };
|
|
|
+ int d = add2_< int_<2>, int_<3> >::value;
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+namespace _5_2
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ template <typename HeadT, typename TailT>
|
|
|
+ class pair_
|
|
|
+ {
|
|
|
+ typedef HeadT head;
|
|
|
+ typedef TailT tail;
|
|
|
+ };
|
|
|
+
|
|
|
+ class Nil;
|
|
|
+
|
|
|
+
|
|
|
+ typedef pair_< int, pair_<float, pair_<double, Nil> > > vector_3;
|
|
|
+
|
|
|
+ template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
|
|
|
+ class make_vector_
|
|
|
+ {
|
|
|
+ typedef pair_< T0, make_vector_<T1, T2, T3> > type;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <>
|
|
|
+ class make_vector_<Nil, Nil, Nil, Nil>
|
|
|
+ {
|
|
|
+ typedef Nil type;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T0, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil>
|
|
|
+ class vector_: public make_vector_<T0, T1, T2, T3>::type
|
|
|
+ {
|
|
|
+ };
|
|
|
+
|
|
|
+ typedef vector_<double, float, int> vector3;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+int _tmain(int argc, _TCHAR* argv[])
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|