C++ Programming Tutorial
Learn modern C++ step-by-step — from basics to advanced features like templates, STL, and smart pointers. Clear explanations with practical, runnable examples.
C++ Templates
Templates let you write generic code that works with any type. The compiler generates type-specific versions at compile time — giving you the flexibility of generics with zero runtime overhead.
Function Templates
func_templates.cpp
#include <iostream>
#include <string>
// A single function that works with any type
template<typename T>
T max_of(T a, T b) {
return (a > b) ? a : b;
}
// Template with multiple type parameters
template<typename T, typename U>
auto add(T a, U b) {
return a + b; // return type deduced (C++14)
}
int main() {
std::cout << max_of(3, 7) << "
"; // 7 (int)
std::cout << max_of(3.14, 2.71) << "
"; // 3.14 (double)
std::cout << max_of(std::string("abc"), std::string("xyz")) << "
"; // xyz
std::cout << add(3, 4.5) << "
"; // 7.5 (int + double = double)
std::cout << add(10, 20) << "
"; // 30
// Explicit template argument (rarely needed)
std::cout << max_of<double>(3, 4.5) << "
";
return 0;
}Class Templates
class_templates.cpp
#include <iostream>
#include <stdexcept>
// A generic stack that works with any type
template<typename T>
class Stack {
T data[100];
int top_index = -1;
public:
void push(const T& value) {
if (top_index >= 99) throw std::overflow_error("Stack full");
data[++top_index] = value;
}
T pop() {
if (top_index < 0) throw std::underflow_error("Stack empty");
return data[top_index--];
}
const T& top() const {
if (top_index < 0) throw std::underflow_error("Stack empty");
return data[top_index];
}
bool empty() const { return top_index < 0; }
int size() const { return top_index + 1; }
};
int main() {
Stack<int> int_stack;
int_stack.push(10);
int_stack.push(20);
std::cout << int_stack.top() << "
"; // 20
int_stack.pop();
std::cout << int_stack.top() << "
"; // 10
Stack<std::string> str_stack;
str_stack.push("hello");
str_stack.push("world");
std::cout << str_stack.top() << "
"; // world
return 0;
}Template Specialization
specialization.cpp
#include <iostream>
#include <cstring>
// General template
template<typename T>
bool is_equal(T a, T b) {
return a == b;
}
// Specialization for C-strings (char*)
template<>
bool is_equal<const char*>(const char* a, const char* b) {
return std::strcmp(a, b) == 0;
}
int main() {
std::cout << is_equal(3, 3) << "
"; // 1 (true)
std::cout << is_equal(3.14, 3.14) << "
"; // 1
std::cout << is_equal("hello", "hello") << "
"; // 1 (uses specialization)
std::cout << is_equal("hi", "bye") << "
"; // 0
return 0;
}Variadic Templates (C++11)
variadic.cpp
#include <iostream>
// Accept any number of arguments of any types
template<typename T>
void print(const T& value) {
std::cout << value << "
"; // base case
}
template<typename T, typename... Rest>
void print(const T& first, const Rest&... rest) {
std::cout << first << " ";
print(rest...); // recursive expansion
}
int main() {
print(1, 2.5, "hello", true);
// Output: 1 2.5 hello 1
return 0;
}Concepts (C++20) — Constraining Templates
concepts.cpp
#include <iostream>
#include <concepts>
// Only allow numeric types
template<typename T>
requires std::integral<T> || std::floating_point<T>
T square(T x) {
return x * x;
}
// Shorter syntax with concept
template<std::integral T>
T double_val(T x) {
return x * 2;
}
int main() {
std::cout << square(5) << "
"; // 25
std::cout << square(3.14) << "
"; // 9.8596
// square("hello"); // ERROR: string is not integral or floating_point
std::cout << double_val(7) << "
"; // 14
return 0;
}Best Practices
- Use templates for type-independent algorithms — avoids code duplication while maintaining type safety.
- Prefer
autoreturn types (C++14) for template functions to simplify declarations. - Use concepts (C++20) to constrain templates — gives clear error messages when wrong types are used.
- Define templates in headers — the compiler needs the full definition to instantiate them.
- Avoid over-engineering — only templatize code that genuinely needs to work with multiple types.
Keep Practicing
Use the online compiler to run every example and experiment with modifications. The best way to learn C++ is by writing code — even small programs build strong foundations.