06_templates.cpp

Download
cpp 316 lines 7.4 KB
  1/*
  2 * Template Metaprogramming Demo
  3 *
  4 * Demonstrates:
  5 * - Function templates and class templates
  6 * - Template specialization
  7 * - Variadic templates
  8 * - SFINAE basics
  9 * - C++20 concepts
 10 * - Type traits
 11 *
 12 * Compile: g++ -std=c++20 -Wall -Wextra 06_templates.cpp -o templates
 13 */
 14
 15#include <iostream>
 16#include <vector>
 17#include <string>
 18#include <type_traits>
 19#include <concepts>
 20
 21// ============ Function Templates ============
 22template<typename T>
 23T my_max(T a, T b) {
 24    return (a > b) ? a : b;
 25}
 26
 27// Template overloading
 28template<typename T>
 29T my_max(T a, T b, T c) {
 30    return my_max(my_max(a, b), c);
 31}
 32
 33void demo_function_templates() {
 34    std::cout << "\n=== Function Templates ===\n";
 35
 36    std::cout << "my_max(10, 20) = " << my_max(10, 20) << "\n";
 37    std::cout << "my_max(3.5, 2.1) = " << my_max(3.5, 2.1) << "\n";
 38    std::cout << "my_max(10, 20, 15) = " << my_max(10, 20, 15) << "\n";
 39
 40    std::string s1 = "hello", s2 = "world";
 41    std::cout << "my_max(\"hello\", \"world\") = " << my_max(s1, s2) << "\n";
 42}
 43
 44// ============ Class Templates ============
 45template<typename T>
 46class Stack {
 47private:
 48    std::vector<T> data_;
 49
 50public:
 51    void push(const T& value) {
 52        data_.push_back(value);
 53    }
 54
 55    void pop() {
 56        if (!data_.empty()) {
 57            data_.pop_back();
 58        }
 59    }
 60
 61    T top() const {
 62        return data_.back();
 63    }
 64
 65    bool empty() const {
 66        return data_.empty();
 67    }
 68
 69    size_t size() const {
 70        return data_.size();
 71    }
 72};
 73
 74void demo_class_templates() {
 75    std::cout << "\n=== Class Templates ===\n";
 76
 77    Stack<int> int_stack;
 78    int_stack.push(10);
 79    int_stack.push(20);
 80    int_stack.push(30);
 81
 82    std::cout << "Int stack top: " << int_stack.top() << "\n";
 83    std::cout << "Int stack size: " << int_stack.size() << "\n";
 84
 85    Stack<std::string> str_stack;
 86    str_stack.push("hello");
 87    str_stack.push("world");
 88
 89    std::cout << "String stack top: " << str_stack.top() << "\n";
 90}
 91
 92// ============ Template Specialization ============
 93template<typename T>
 94class Printer {
 95public:
 96    static void print(const T& value) {
 97        std::cout << "Generic: " << value << "\n";
 98    }
 99};
100
101// Full specialization for bool
102template<>
103class Printer<bool> {
104public:
105    static void print(const bool& value) {
106        std::cout << "Bool: " << (value ? "true" : "false") << "\n";
107    }
108};
109
110// Partial specialization for pointers
111template<typename T>
112class Printer<T*> {
113public:
114    static void print(T* value) {
115        std::cout << "Pointer: " << static_cast<void*>(value);
116        if (value) {
117            std::cout << " -> " << *value;
118        }
119        std::cout << "\n";
120    }
121};
122
123void demo_specialization() {
124    std::cout << "\n=== Template Specialization ===\n";
125
126    Printer<int>::print(42);
127    Printer<bool>::print(true);
128
129    int x = 100;
130    Printer<int*>::print(&x);
131}
132
133// ============ Variadic Templates ============
134// Base case
135void print() {
136    std::cout << "\n";
137}
138
139// Recursive case
140template<typename T, typename... Args>
141void print(T first, Args... rest) {
142    std::cout << first << " ";
143    print(rest...);
144}
145
146// Variadic sum using fold expression (C++17)
147template<typename... Args>
148auto sum(Args... args) {
149    return (args + ...);
150}
151
152void demo_variadic_templates() {
153    std::cout << "\n=== Variadic Templates ===\n";
154
155    std::cout << "print(1, 2, 3, \"hello\", 3.14): ";
156    print(1, 2, 3, "hello", 3.14);
157
158    std::cout << "sum(1, 2, 3, 4, 5) = " << sum(1, 2, 3, 4, 5) << "\n";
159    std::cout << "sum(1.5, 2.5, 3.0) = " << sum(1.5, 2.5, 3.0) << "\n";
160}
161
162// ============ SFINAE (Substitution Failure Is Not An Error) ============
163// Enable if T is integral
164template<typename T>
165typename std::enable_if<std::is_integral<T>::value, T>::type
166double_value(T value) {
167    return value * 2;
168}
169
170// Enable if T is floating point
171template<typename T>
172typename std::enable_if<std::is_floating_point<T>::value, T>::type
173double_value(T value) {
174    return value * 2.0;
175}
176
177void demo_sfinae() {
178    std::cout << "\n=== SFINAE ===\n";
179
180    std::cout << "double_value(10) = " << double_value(10) << "\n";
181    std::cout << "double_value(3.5) = " << double_value(3.5) << "\n";
182
183    // This would fail to compile:
184    // double_value("hello");
185}
186
187// ============ C++20 Concepts ============
188template<typename T>
189concept Numeric = std::integral<T> || std::floating_point<T>;
190
191template<typename T>
192concept Addable = requires(T a, T b) {
193    { a + b } -> std::convertible_to<T>;
194};
195
196template<Numeric T>
197T triple(T value) {
198    return value * 3;
199}
200
201template<Addable T>
202T add_three(T a, T b, T c) {
203    return a + b + c;
204}
205
206void demo_concepts() {
207    std::cout << "\n=== C++20 Concepts ===\n";
208
209    std::cout << "triple(10) = " << triple(10) << "\n";
210    std::cout << "triple(3.5) = " << triple(3.5) << "\n";
211
212    std::cout << "add_three(1, 2, 3) = " << add_three(1, 2, 3) << "\n";
213    std::cout << "add_three(1.5, 2.5, 3.0) = " << add_three(1.5, 2.5, 3.0) << "\n";
214
215    // These would fail to compile:
216    // triple("hello");
217    // add_three("a", "b", "c");  // strings are Addable but behave differently
218}
219
220// ============ Type Traits ============
221template<typename T>
222void analyze_type(T value) {
223    std::cout << "Type analysis for value: " << value << "\n";
224    std::cout << "  is_integral: " << std::is_integral_v<T> << "\n";
225    std::cout << "  is_floating_point: " << std::is_floating_point_v<T> << "\n";
226    std::cout << "  is_pointer: " << std::is_pointer_v<T> << "\n";
227    std::cout << "  is_const: " << std::is_const_v<T> << "\n";
228    std::cout << "  is_arithmetic: " << std::is_arithmetic_v<T> << "\n";
229}
230
231void demo_type_traits() {
232    std::cout << "\n=== Type Traits ===\n";
233
234    analyze_type(42);
235    analyze_type(3.14);
236
237    int x = 10;
238    analyze_type(&x);
239}
240
241// ============ Template Template Parameters ============
242template<typename T, template<typename> class Container>
243class Wrapper {
244private:
245    Container<T> data_;
246
247public:
248    void add(const T& value) {
249        data_.push_back(value);
250    }
251
252    void print() const {
253        std::cout << "  Container contents: ";
254        for (const auto& item : data_) {
255            std::cout << item << " ";
256        }
257        std::cout << "\n";
258    }
259};
260
261void demo_template_template() {
262    std::cout << "\n=== Template Template Parameters ===\n";
263
264    Wrapper<int, std::vector> wrapper;
265    wrapper.add(10);
266    wrapper.add(20);
267    wrapper.add(30);
268    wrapper.print();
269}
270
271// ============ Compile-Time Computation ============
272template<int N>
273struct Factorial {
274    static constexpr int value = N * Factorial<N - 1>::value;
275};
276
277template<>
278struct Factorial<0> {
279    static constexpr int value = 1;
280};
281
282// C++11 constexpr function
283constexpr int factorial(int n) {
284    return (n <= 1) ? 1 : n * factorial(n - 1);
285}
286
287void demo_compile_time() {
288    std::cout << "\n=== Compile-Time Computation ===\n";
289
290    std::cout << "Factorial<5>::value = " << Factorial<5>::value << "\n";
291    std::cout << "factorial(5) = " << factorial(5) << "\n";
292
293    // These are computed at compile time
294    constexpr int fact10 = factorial(10);
295    std::cout << "factorial(10) = " << fact10 << "\n";
296}
297
298// ============ Main ============
299int main() {
300    std::cout << "Template Metaprogramming Demo\n";
301    std::cout << "==============================\n";
302
303    demo_function_templates();
304    demo_class_templates();
305    demo_specialization();
306    demo_variadic_templates();
307    demo_sfinae();
308    demo_concepts();
309    demo_type_traits();
310    demo_template_template();
311    demo_compile_time();
312
313    std::cout << "\nAll demos completed!\n";
314    return 0;
315}