cpp
examples
examples.cpp⚙️cpp
/**
* Preprocessor Directives & Namespaces - Examples
* Comprehensive demonstration of all preprocessor features and namespaces
*/
#include <iostream>
#include <string>
#include <chrono>
using std::cout;
using std::endl;
using std::string;
// ============================================================================
// SECTION 1: Basic Macros
// ============================================================================
// Object-like macros (constants)
#define MACRO_PI 3.14159265359 // ⚠️ LEARNING NOTE: Renamed from PI!
// PROBLEM: Later in this file, we also define 'const double PI'
// Macros are text replacement - the compiler sees:
// const double 3.14159265359 = 3.14159265359; // ERROR!
//
// LESSON: Avoid naming macros the same as variables!
// Better practice: Use ALL_CAPS with prefix for macros, or use constexpr instead
#define MAX_BUFFER_SIZE 1024
#define APP_VERSION "1.0.0"
#define ENABLE_LOGGING
// Function-like macros
#define SQUARE(x) ((x) * (x))
#define CUBE(x) ((x) * (x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
// Stringification
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
// Token pasting
#define MAKE_FUNCTION(name) void name##_function() { cout << #name " function called" << endl; }
#define DECLARE_VAR(type, name) type var_##name
void demonstrateBasicMacros() {
cout << "\n=== BASIC MACROS ===" << endl;
// Object-like macros
// ⚠️ Note: We use MACRO_PI here (not PI) to avoid conflict with Math::PI later
cout << "MACRO_PI = " << MACRO_PI << endl;
cout << "MAX_BUFFER_SIZE = " << MAX_BUFFER_SIZE << endl;
cout << "APP_VERSION = " << APP_VERSION << endl;
// Function-like macros
cout << "\nFunction-like macros:" << endl;
cout << "SQUARE(5) = " << SQUARE(5) << endl;
cout << "CUBE(3) = " << CUBE(3) << endl;
cout << "MAX(10, 20) = " << MAX(10, 20) << endl;
cout << "MIN(10, 20) = " << MIN(10, 20) << endl;
cout << "ABS(-15) = " << ABS(-15) << endl;
// Demonstrating why parentheses matter
cout << "\nWhy parentheses matter in SQUARE:" << endl;
cout << "SQUARE(2 + 3) = " << SQUARE(2 + 3) << " (correct: 25)" << endl;
// Without parentheses it would be: 2 + 3 * 2 + 3 = 11
// Stringification
cout << "\nStringification:" << endl;
cout << "STRINGIFY(Hello World) = " << STRINGIFY(Hello World) << endl;
cout << "TOSTRING(12345) = " << TOSTRING(12345) << endl;
cout << "TOSTRING(MAX_BUFFER_SIZE) = " << TOSTRING(MAX_BUFFER_SIZE) << endl;
// Token pasting
cout << "\nToken pasting - declaring variables:" << endl;
DECLARE_VAR(int, count) = 42;
DECLARE_VAR(double, value) = 3.14;
cout << "var_count = " << var_count << endl;
cout << "var_value = " << var_value << endl;
}
// Create functions using macro
MAKE_FUNCTION(test)
MAKE_FUNCTION(demo)
void demonstrateGeneratedFunctions() {
cout << "\n=== MACRO-GENERATED FUNCTIONS ===" << endl;
test_function();
demo_function();
}
// ============================================================================
// SECTION 2: Predefined Macros
// ============================================================================
void demonstratePredefinedMacros() {
cout << "\n=== PREDEFINED MACROS ===" << endl;
cout << "File: " << __FILE__ << endl;
cout << "Line: " << __LINE__ << endl;
cout << "Date: " << __DATE__ << endl;
cout << "Time: " << __TIME__ << endl;
cout << "Function: " << __func__ << endl;
// C++ standard version
cout << "\nC++ Standard Version: ";
#if __cplusplus >= 202002L
cout << "C++20 or later";
#elif __cplusplus >= 201703L
cout << "C++17";
#elif __cplusplus >= 201402L
cout << "C++14";
#elif __cplusplus >= 201103L
cout << "C++11";
#else
cout << "Pre-C++11";
#endif
cout << " (__cplusplus = " << __cplusplus << ")" << endl;
}
// ============================================================================
// SECTION 3: Conditional Compilation
// ============================================================================
// Define debug level
#define DEBUG_LEVEL 2
// Conditional logging based on debug level
#if DEBUG_LEVEL == 0
#define LOG(msg)
#define LOG_DEBUG(msg)
#define LOG_VERBOSE(msg)
#elif DEBUG_LEVEL == 1
#define LOG(msg) cout << "[LOG] " << msg << endl
#define LOG_DEBUG(msg)
#define LOG_VERBOSE(msg)
#elif DEBUG_LEVEL >= 2
#define LOG(msg) cout << "[LOG] " << msg << endl
#define LOG_DEBUG(msg) cout << "[DEBUG] " << __func__ << ":" << __LINE__ << " - " << msg << endl
#define LOG_VERBOSE(msg) cout << "[VERBOSE] " << __FILE__ << ":" << __LINE__ << " - " << msg << endl
#endif
void demonstrateConditionalCompilation() {
cout << "\n=== CONDITIONAL COMPILATION ===" << endl;
cout << "DEBUG_LEVEL = " << DEBUG_LEVEL << endl;
LOG("This is a log message");
LOG_DEBUG("This is a debug message");
LOG_VERBOSE("This is a verbose message");
// ifdef/ifndef
#ifdef ENABLE_LOGGING
cout << "\nLogging is ENABLED" << endl;
#else
cout << "\nLogging is DISABLED" << endl;
#endif
#ifndef PRODUCTION
cout << "Not in production mode" << endl;
#endif
}
// ============================================================================
// SECTION 4: Platform Detection
// ============================================================================
void demonstratePlatformDetection() {
cout << "\n=== PLATFORM DETECTION ===" << endl;
#if defined(_WIN32) || defined(_WIN64)
cout << "Platform: Windows" << endl;
#ifdef _WIN64
cout << "Architecture: 64-bit" << endl;
#else
cout << "Architecture: 32-bit" << endl;
#endif
#elif defined(__linux__)
cout << "Platform: Linux" << endl;
#elif defined(__APPLE__) && defined(__MACH__)
cout << "Platform: macOS" << endl;
#elif defined(__FreeBSD__)
cout << "Platform: FreeBSD" << endl;
#else
cout << "Platform: Unknown" << endl;
#endif
// Compiler detection
cout << "\nCompiler: ";
#if defined(__clang__)
cout << "Clang " << __clang_major__ << "." << __clang_minor__ << endl;
#elif defined(__GNUC__)
cout << "GCC " << __GNUC__ << "." << __GNUC_MINOR__ << endl;
#elif defined(_MSC_VER)
cout << "MSVC " << _MSC_VER << endl;
#else
cout << "Unknown" << endl;
#endif
}
// ============================================================================
// SECTION 5: Namespaces
// ============================================================================
namespace Math {
const double PI = 3.14159265359;
const double E = 2.71828182845;
double square(double x) { return x * x; }
double cube(double x) { return x * x * x; }
double circleArea(double radius) { return PI * square(radius); }
double sphereVolume(double radius) { return (4.0/3.0) * PI * cube(radius); }
}
namespace Physics {
const double G = 9.81; // Gravity (m/s²)
const double C = 299792458; // Speed of light (m/s)
double velocity(double distance, double time) {
return distance / time;
}
double kineticEnergy(double mass, double velocity) {
return 0.5 * mass * velocity * velocity;
}
}
namespace Utilities {
namespace String {
string toUpper(string s) {
for (char& c : s) c = toupper(c);
return s;
}
string toLower(string s) {
for (char& c : s) c = tolower(c);
return s;
}
}
namespace Math { // Different from global Math namespace
int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
}
}
void demonstrateNamespaces() {
cout << "\n=== NAMESPACES ===" << endl;
// Fully qualified names
cout << "Math::PI = " << Math::PI << endl;
cout << "Math::circleArea(5) = " << Math::circleArea(5) << endl;
cout << "Math::sphereVolume(3) = " << Math::sphereVolume(3) << endl;
cout << "\nPhysics::G = " << Physics::G << endl;
cout << "Physics::velocity(100, 10) = " << Physics::velocity(100, 10) << endl;
cout << "Physics::kineticEnergy(10, 5) = " << Physics::kineticEnergy(10, 5) << endl;
// Nested namespaces
cout << "\nUtilities::String::toUpper(\"hello\") = "
<< Utilities::String::toUpper("hello") << endl;
cout << "Utilities::Math::factorial(5) = "
<< Utilities::Math::factorial(5) << endl;
}
// C++17 nested namespace syntax
namespace Company::Product::Feature {
void doSomething() {
cout << "Feature activated!" << endl;
}
}
// Namespace alias
namespace CPF = Company::Product::Feature;
void demonstrateNestedNamespaces() {
cout << "\n=== NESTED NAMESPACES (C++17) ===" << endl;
Company::Product::Feature::doSomething();
// Using alias
cout << "Using namespace alias:" << endl;
CPF::doSomething();
}
// ============================================================================
// SECTION 6: using Declarations and Directives
// ============================================================================
namespace Graphics {
struct Point { int x, y; };
struct Color { int r, g, b; };
void drawPoint(Point p) {
cout << "Drawing point at (" << p.x << ", " << p.y << ")" << endl;
}
void setColor(Color c) {
cout << "Setting color to RGB(" << c.r << ", " << c.g << ", " << c.b << ")" << endl;
}
}
void demonstrateUsingDeclarations() {
cout << "\n=== using DECLARATIONS ===" << endl;
// using declaration - bring specific names into scope
using Graphics::Point;
using Graphics::drawPoint;
Point p{10, 20};
drawPoint(p);
// Still need full qualification for other members
Graphics::Color color{255, 128, 0};
Graphics::setColor(color);
}
void demonstrateUsingDirective() {
cout << "\n=== using DIRECTIVE (in function scope) ===" << endl;
// using directive - bring all names into scope
// Safe here because it's in function scope
using namespace Graphics;
Point p1{5, 10};
Point p2{15, 25};
Color red{255, 0, 0};
drawPoint(p1);
drawPoint(p2);
setColor(red);
}
// ============================================================================
// SECTION 7: Anonymous Namespace
// ============================================================================
// Anonymous namespace - internal linkage
namespace {
int internalCounter = 0;
void internalHelper() {
cout << "Internal helper called, counter = " << ++internalCounter << endl;
}
}
void demonstrateAnonymousNamespace() {
cout << "\n=== ANONYMOUS NAMESPACE ===" << endl;
cout << "These functions/variables have internal linkage (file-private)" << endl;
internalHelper();
internalHelper();
internalHelper();
}
// ============================================================================
// SECTION 8: Inline Namespace (Library Versioning)
// ============================================================================
namespace MyLibrary {
inline namespace v2 { // Current default version
struct Data {
int value;
string name;
void print() const {
cout << "v2::Data{value=" << value << ", name=\"" << name << "\"}" << endl;
}
};
}
namespace v1 { // Legacy version
struct Data {
int value;
void print() const {
cout << "v1::Data{value=" << value << "}" << endl;
}
};
}
}
void demonstrateInlineNamespace() {
cout << "\n=== INLINE NAMESPACE (Versioning) ===" << endl;
// Uses v2 by default (inline namespace)
MyLibrary::Data current{42, "Modern"};
current.print();
// Explicitly use v1
MyLibrary::v1::Data legacy{100};
legacy.print();
// Explicitly use v2
MyLibrary::v2::Data explicit_v2{200, "Explicit"};
explicit_v2.print();
}
// ============================================================================
// SECTION 9: Practical Debug Macro System
// ============================================================================
// Undefine previous logging macros
#undef LOG
#undef LOG_DEBUG
#undef LOG_VERBOSE
// Production-ready debug macro system
#define DEBUG_ENABLED
#ifdef DEBUG_ENABLED
#define ASSERT(condition, message) \
do { \
if (!(condition)) { \
std::cerr << "ASSERTION FAILED: " << message << "\n" \
<< " Condition: " << #condition << "\n" \
<< " File: " << __FILE__ << "\n" \
<< " Line: " << __LINE__ << "\n" \
<< " Function: " << __func__ << std::endl; \
} \
} while(0)
#define DEBUG_LOG(msg) \
cout << "[DEBUG] " << __func__ << ": " << msg << endl
#define TRACE_ENTER() \
cout << "[TRACE] Entering: " << __func__ << endl
#define TRACE_EXIT() \
cout << "[TRACE] Exiting: " << __func__ << endl
#else
#define ASSERT(condition, message) ((void)0)
#define DEBUG_LOG(msg) ((void)0)
#define TRACE_ENTER() ((void)0)
#define TRACE_EXIT() ((void)0)
#endif
void demonstratePracticalMacros() {
TRACE_ENTER();
cout << "\n=== PRACTICAL DEBUG MACRO SYSTEM ===" << endl;
int value = 42;
DEBUG_LOG("Value is " << value);
ASSERT(value > 0, "Value should be positive");
ASSERT(value < 100, "Value should be less than 100");
// This assertion will fail and print debug info
// ASSERT(value > 100, "This will fail");
TRACE_EXIT();
}
// ============================================================================
// SECTION 10: Compile-Time Profiling Macros
// ============================================================================
#define ENABLE_PROFILING
#ifdef ENABLE_PROFILING
#define PROFILE_SCOPE(name) \
auto _profile_start_##name = std::chrono::high_resolution_clock::now(); \
struct _ProfileScope_##name { \
const char* _name; \
decltype(_profile_start_##name) _start; \
_ProfileScope_##name(const char* n, decltype(_profile_start_##name) s) : _name(n), _start(s) {} \
~_ProfileScope_##name() { \
auto _end = std::chrono::high_resolution_clock::now(); \
auto _duration = std::chrono::duration<double, std::milli>(_end - _start); \
cout << "[PROFILE] " << _name << ": " << _duration.count() << " ms" << endl; \
} \
} _profile_instance_##name(#name, _profile_start_##name)
#else
#define PROFILE_SCOPE(name)
#endif
void demonstrateProfilingMacros() {
cout << "\n=== PROFILING MACROS ===" << endl;
{
PROFILE_SCOPE(StringOperations);
string result;
for (int i = 0; i < 10000; ++i) {
result += "x";
}
}
{
PROFILE_SCOPE(MathCalculations);
double sum = 0;
for (int i = 0; i < 100000; ++i) {
sum += Math::square(i) + Math::cube(i % 100);
}
}
}
// ============================================================================
// MAIN
// ============================================================================
int main() {
cout << "╔══════════════════════════════════════════════════════════════╗" << endl;
cout << "║ PREPROCESSOR DIRECTIVES & NAMESPACES EXAMPLES ║" << endl;
cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
// Macro examples
demonstrateBasicMacros();
demonstrateGeneratedFunctions();
demonstratePredefinedMacros();
demonstrateConditionalCompilation();
demonstratePlatformDetection();
// Namespace examples
demonstrateNamespaces();
demonstrateNestedNamespaces();
demonstrateUsingDeclarations();
demonstrateUsingDirective();
demonstrateAnonymousNamespace();
demonstrateInlineNamespace();
// Practical examples
demonstratePracticalMacros();
demonstrateProfilingMacros();
cout << "\n═══════════════════════════════════════════════════════════════" << endl;
cout << "All examples completed!" << endl;
return 0;
}