C++14coreintermediate
Variable Templates
C++14 · Modern Refined · Compiler flag: -std=c++14
Explanation
Variables can now be templated, allowing a single definition to produce different constants or variables for different types. This is cleaner than wrapping constants inside class templates or function templates and is particularly useful for mathematical and physical constants.
Real-World Scenario
A 3D rendering engine defines mathematical constants like pi and epsilon as variable templates so that the same constant name works seamlessly with `float`, `double`, and `long double` pipelines without loss of precision.
Quick Snippet
snippet.cpp
#include <iostream>
#include <iomanip>
template<typename T>
constexpr T pi = T(3.14159265358979323846L);
template<typename T>
constexpr T epsilon = T(1e-7L);
int main() {
float area_f = pi<float> * 5.0f * 5.0f;
double area_d = pi<double> * 5.0 * 5.0;
std::cout << std::setprecision(15) << area_f << "\n" << area_d << "\n";
}Full Example
variable_templates.cpp
// CodeNebula - C++14 Example: Variable Templates
// Compile: g++ -std=c++14 -Wall -Wextra -o example variable_templates.cpp
// Demonstrates variable templates introduced in C++14. A variable template
// defines a family of variables parameterized by type. Real-world use:
// type-specific constants like pi<float> vs pi<double>, compile-time
// configuration values, and cleaner trait-style boolean checks.
#include <iostream>
#include <cmath>
#include <iomanip>
#include <type_traits>
// ------------------------------------------------------------------
// 1. Classic use case: mathematical constants with appropriate precision
// ------------------------------------------------------------------
template<typename T>
constexpr T pi = T(3.14159265358979323846264338327950288L);
template<typename T>
constexpr T e = T(2.71828182845904523536028747135266250L);
template<typename T>
constexpr T golden_ratio = T(1.61803398874989484820458683436563812L);
// ------------------------------------------------------------------
// 2. Type trait shortcut (like C++17's _v traits, but hand-rolled)
// ------------------------------------------------------------------
template<typename T>
constexpr bool is_integral_v = std::is_integral<T>::value;
template<typename T>
constexpr bool is_floating_point_v = std::is_floating_point<T>::value;
// ------------------------------------------------------------------
// 3. Configuration constants per type
// ------------------------------------------------------------------
template<typename T>
constexpr T default_tolerance = T(1e-6);
template<>
constexpr float default_tolerance<float> = 1e-4f; // specialization
template<>
constexpr double default_tolerance<double> = 1e-10;
// ------------------------------------------------------------------
// Helper: compute circle area using variable template pi
// ------------------------------------------------------------------
template<typename T>
T circle_area(T radius)
{
return pi<T> * radius * radius;
}
int main()
{
std::cout << std::setprecision(15);
// ------------------------------------------------------------------
// 1. Mathematical constants with different precisions
// ------------------------------------------------------------------
std::cout << "=== Mathematical Constants ===" << std::endl;
std::cout << " pi<float> : " << pi<float> << std::endl;
std::cout << " pi<double> : " << pi<double> << std::endl;
std::cout << " pi<long double> : " << static_cast<double>(pi<long double>) << std::endl;
std::cout << " e<double> : " << e<double> << std::endl;
std::cout << " golden_ratio<dbl>: " << golden_ratio<double> << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 2. Using constants in computations
// ------------------------------------------------------------------
std::cout << "=== Circle Area (radius=5) ===" << std::endl;
std::cout << std::setprecision(6);
std::cout << " float : " << circle_area(5.0f) << std::endl;
std::cout << " double : " << circle_area(5.0) << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 3. Type trait variable templates
// ------------------------------------------------------------------
std::cout << "=== Type Trait Variable Templates ===" << std::endl;
std::cout << std::boolalpha;
std::cout << " is_integral_v<int> : " << is_integral_v<int> << std::endl;
std::cout << " is_integral_v<double> : " << is_integral_v<double> << std::endl;
std::cout << " is_floating_point_v<float>: " << is_floating_point_v<float> << std::endl;
std::cout << " is_floating_point_v<int> : " << is_floating_point_v<int> << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 4. Specialized tolerance values
// ------------------------------------------------------------------
std::cout << "=== Specialized Tolerances ===" << std::endl;
std::cout << std::setprecision(15);
std::cout << " default_tolerance<float> : " << default_tolerance<float> << std::endl;
std::cout << " default_tolerance<double> : " << default_tolerance<double> << std::endl;
return 0;
}
/*
Expected output:
=== Mathematical Constants ===
pi<float> : 3.14159274101257
pi<double> : 3.14159265358979
pi<long double> : 3.14159265358979
e<double> : 2.71828182845905
golden_ratio<dbl>: 1.61803398874989
=== Circle Area (radius=5) ===
float : 78.5398
double : 78.5398
=== Type Trait Variable Templates ===
is_integral_v<int> : true
is_integral_v<double> : false
is_floating_point_v<float>: true
is_floating_point_v<int> : false
=== Specialized Tolerances ===
default_tolerance<float> : 0.000100000004749745
default_tolerance<double> : 1e-10
*/
Run command
g++ -std=c++14 -Wall -Wextra -o example variable_templates.cpp