SFINAE (Substitution Failure Is Not An Error) — if template substitution fails, try other overloads.
1#include <type_traits>23// Enable if T has begin/end (is iterable)4template<typename T>5auto print_container(const T& container) ->6 std::enable_if_t<7 std::is_same_v<8 decltype(std::declval<T>().begin()),9 decltype(std::declval<T>().end())10 >11 >12{13 for (const auto& item : container) {14 std::cout << item << " ";15 }16 std::cout << "\n";17}1819// Fallback for non-iterable20template<typename T>21void print_container(const T& value) {22 std::cout << value << "\n";23}2425int main() {26 print_container(std::vector<int>{1, 2, 3}); // OK27 print_container(42); // Fallback28}
Modern C++17 (if constexpr):
1template<typename T>2void print(const T& value) {3 if constexpr (std::is_integral_v<T>) {4 std::cout << "Integer: " << value << "\n";5 } else if constexpr (std::is_floating_point_v<T>) {6 std::cout << "Float: " << value << "\n";7 } else {8 std::cout << "Other: " << value << "\n";9 }10}
Concepts (C++20):
1template<std::integral T>2void print(T value) {3 std::cout << value << "\n";4}