Skip to content

Commit 70d71e6

Browse files
authored
[cpplings] Add template programming exercises (#526)
### What problem were solved in this pull request? Issue Number: #523 Problem: - Missing C++ template programming exercises, affecting contributors' understanding and application of C++ templates - Need to enhance the cpplings exercise collection to support the goal of Issue #508 ### What is changed and how it works? - Added template_basics.cpp file, implementing: - Basic function template examples showing how to create generic functions - Class template implementation and usage, demonstrating definition and usage of generic classes - Template specialization techniques with a specialized version for string type - Recursive implementation of variadic templates, showing how to handle variable parameter lists - SFINAE technique application, selecting different function implementations based on type traits - Added comprehensive comments explaining template programming concepts and use cases - Included complete test code to ensure examples run correctly ### Other information - Run the test case with `./bin/cpplings template_basics` - Parent Issue: #508 (add more cpplings case)
1 parent 8dcaa27 commit 70d71e6

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

src/cpplings/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ add_custom_executable(lambda lambda.cpp)
1313
add_custom_executable(lock lock.cpp)
1414
add_custom_executable(mutex mutex.cpp)
1515
add_custom_executable(smart_pointer smart_pointer.cpp)
16+
add_custom_executable(template template.cpp)

src/cpplings/template.cpp

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
2+
miniob is licensed under Mulan PSL v2.
3+
You can use this software according to the terms and conditions of the Mulan PSL v2.
4+
You may obtain a copy of Mulan PSL v2 at:
5+
http://license.coscl.org.cn/MulanPSL2
6+
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7+
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8+
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9+
See the Mulan PSL v2 for more details. */
10+
11+
// 模板编程是C++中的一种强大特性,允许开发者编写与类型无关的代码。
12+
// 模板可以应用于函数、类和变量,使开发者能够编写通用的算法和数据结构。
13+
//
14+
// C++模板主要分为函数模板和类模板两种:
15+
// 函数模板允许创建可以处理多种数据类型的函数,而不必为每种类型编写单独的函数。
16+
// 类模板允许创建可以存储和处理多种数据类型的通用类,例如STL中的容器。
17+
// 模板特化允许为特定的类型提供专门的实现。
18+
// 变参模板支持接受可变数量的参数,非常适用于构建递归数据结构和算法。
19+
// SFINAE(Substitution Failure Is Not An Error)是一种模板编程技术,它允许在编译时根据类型特性选择正确的
20+
// 函数重载或模板特化。当模板参数替换失败时,不会产生编译错误,而是简单地从重载解析
21+
// 集合中删除该函数。
22+
#include <iostream>
23+
#include <type_traits>
24+
#include <vector>
25+
#include <string>
26+
27+
// 1. 基础函数模板
28+
template <typename T>
29+
T max_value(T a, T b)
30+
{
31+
return (a > b) ? a : b;
32+
}
33+
34+
// 2. 类模板
35+
template <typename T>
36+
class Container
37+
{
38+
private:
39+
T data;
40+
41+
public:
42+
Container(T value) : data(value) {}
43+
44+
T get_data() const { return data; }
45+
46+
void set_data(T value) { data = value; }
47+
};
48+
49+
// 3. 模板特化 - 为std::string类型提供特殊实现
50+
template <>
51+
class Container<std::string>
52+
{
53+
private:
54+
std::string data;
55+
56+
public:
57+
Container(std::string value) : data(value) {}
58+
59+
std::string get_data() const { return data; }
60+
61+
void set_data(std::string value) { data = value; }
62+
63+
// 字符串类型特有的方法
64+
std::size_t length() const { return data.length(); }
65+
};
66+
67+
// 4. 变参模板 - 递归终止条件
68+
template <typename T>
69+
T sum(T value)
70+
{
71+
return value;
72+
}
73+
74+
// 变参模板 - 递归调用
75+
template <typename T, typename... Args>
76+
T sum(T first, Args... args)
77+
{
78+
return first + sum(args...);
79+
}
80+
81+
// 5. SFINAE技术示例
82+
// SFINAE (Substitution Failure Is Not An Error) 是C++模板编程中的重要概念:
83+
// - 它允许编译器在模板替换过程中,当某个替换导致无效代码时,不产生错误而是继续尝试其他候选函数
84+
// - 常用于根据类型特性选择不同的函数实现,是C++中实现"编译期多态"的重要机制
85+
86+
// 以下示例展示如何使用SFINAE检测类型是否支持特定操作
87+
template <typename T>
88+
typename std::enable_if<std::is_integral<T>::value, bool>::type is_positive(T value)
89+
{
90+
return value > 0;
91+
}
92+
93+
// 启用仅当T是浮点类型时的函数
94+
template <typename T>
95+
typename std::enable_if<std::is_floating_point<T>::value, bool>::type is_positive(T value)
96+
{
97+
return value > 0.0;
98+
}
99+
100+
int main()
101+
{
102+
// 1. 测试函数模板
103+
std::cout << "Function template examples:" << std::endl;
104+
std::cout << "max_value(10, 20): " << max_value(10, 20) << std::endl;
105+
std::cout << "max_value(3.14, 2.71): " << max_value(3.14, 2.71) << std::endl;
106+
std::cout << "max_value(\"apple\", \"banana\"): " << max_value<std::string>("apple", "banana") << std::endl;
107+
108+
// 2. 测试类模板
109+
std::cout << "\nClass template examples:" << std::endl;
110+
Container<int> int_container(42);
111+
std::cout << "int_container.get_data(): " << int_container.get_data() << std::endl;
112+
113+
Container<double> double_container(3.14159);
114+
std::cout << "double_container.get_data(): " << double_container.get_data() << std::endl;
115+
116+
// 3. 测试模板特化
117+
std::cout << "\nTemplate specialization examples:" << std::endl;
118+
Container<std::string> string_container("Hello Templates!");
119+
std::cout << "string_container.get_data(): " << string_container.get_data() << std::endl;
120+
std::cout << "string_container.length(): " << string_container.length() << std::endl;
121+
122+
// 4. 测试变参模板
123+
std::cout << "\nVariadic template examples:" << std::endl;
124+
std::cout << "sum(1): " << sum(1) << std::endl;
125+
std::cout << "sum(1, 2, 3, 4, 5): " << sum(1, 2, 3, 4, 5) << std::endl;
126+
std::cout << "sum(1.1, 2.2, 3.3): " << sum(1.1, 2.2, 3.3) << std::endl;
127+
128+
// 5. 测试SFINAE
129+
std::cout << "\nSFINAE examples:" << std::endl;
130+
// - 对于整数类型,调用的是以">0"判断正负的版本
131+
std::cout << "is_positive(42): " << (is_positive(42) ? "true" : "false") << std::endl;
132+
std::cout << "is_positive(-42): " << (is_positive(-42) ? "true" : "false") << std::endl;
133+
// - 对于浮点类型,调用的是用">0.0"判断正负的版本
134+
std::cout << "is_positive(3.14): " << (is_positive(3.14) ? "true" : "false") << std::endl;
135+
std::cout << "is_positive(-3.14): " << (is_positive(-3.14) ? "true" : "false") << std::endl;
136+
137+
std::cout << "\npassed!" << std::endl;
138+
return 0;
139+
}

0 commit comments

Comments
 (0)