Function Overloading and Resolution
Unlike C, C++ allows multiple functions with the same name but different parameter lists. The compiler selects the appropriate overload through overload resolution at compile time based on argument types.
void print(int x) { std::cout << "int: " << x; }
void print(double x) { std::cout << "double: " << x; }
void print(const char* x) { std::cout << "string: " << x; }
print(42); // Calls print(int)
print(3.14); // Calls print(double)
print("hello"); // Calls print(const char*)
Overload Resolution Rules
The compiler follows a precise algorithm:
- Exact match: Argument type matches parameter exactly
- Promotion: Integral promotions (
char→int) orfloat→double - Standard conversion: Numeric conversions, pointer conversions
- User-defined conversion: Via conversion operators or constructors
- Ellipsis match: Variadic functions (least preferred)
If multiple functions match at the same level, the call is ambiguous and compilation fails.
void process(int x) { }
void process(double x) { }
process(42L); // Error: ambiguous (long can convert to int or double)
Overload Resolution
void func(int) { } void func(double) { } void func(const char*) { } func(); // Calls func(int) - exact match
Default Arguments
Functions can specify default values for trailing parameters. Defaults are evaluated at call site, not function definition.
void configure(int timeout = 30, bool verbose = false);
configure(); // configure(30, false)
configure(60); // configure(60, false)
configure(60, true); // configure(60, true)
// configure(, true); // Error: can't skip non-trailing arguments
Best Practice: Declare defaults in header files (declarations), not source files (definitions). This ensures callers see the defaults.
// header.hpp
void setup(int port = 8080);
// source.cpp
void setup(int port) { // No default here
// implementation
}
Inline Functions and ODR
The inline keyword suggests the compiler should substitute the function body at call sites, eliminating call overhead. Modern compilers ignore this hint and inline based on optimization heuristics.
However, inline has a critical semantic meaning: it relaxes the One Definition Rule, allowing identical definitions in multiple translation units.
// header.hpp
inline int square(int x) {
return x * x;
}
// Can be included in multiple .cpp files without linker errors
Modern Usage: inline is essential for defining functions in headers, especially templates and constexpr functions (implicitly inline).
Function Templates
Templates enable generic programming by allowing functions to operate on any type satisfying certain requirements.
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
auto x = max(10, 20); // T = int
auto y = max(3.14, 2.71); // T = double
auto z = max<long>(5, 10); // Explicit T = long
Template Argument Deduction
The compiler deduces template parameters from function arguments. Deduction fails if types are ambiguous:
template<typename T>
void process(T a, T b) { }
process(10, 20); // OK: T = int
process(10, 3.14); // Error: T is int or double?
process<double>(10, 3.14); // OK: explicit T = double
Template Specialization
You can provide specialized implementations for specific types:
template<typename T>
T zero() { return T{}; }
template<>
const char* zero<const char*>() { return ""; }
Trailing Return Types
C++11 allows return type after parameter list, useful when return type depends on parameters:
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
C++14 simplified this with return type deduction:
template<typename T, typename U>
auto add(T t, U u) {
return t + u; // Type deduced from return statement
}
constexpr Functions
Functions marked constexpr can execute at compile time if arguments are constant expressions:
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
constexpr auto result = factorial(5); // Computed at compile time
int arr[factorial(4)]; // Array size must be compile-time constant
C++14 relaxed restrictions, allowing loops and multiple statements in constexpr functions.
What happens when `inline` is applied to a function?
Interactive Lab
Waiting for signal...