60 Second Lesson: C++ Token Pasting Metaprogramming

Token Pasting Metaprogramming

C++ token pasting metaprogramming provides intermediate developers with a low-friction way to generate near-identical classes without wrestling with heavyweight template tricks.

By combining the pre‑processor’s ## operator with non‑type template parameters (NTTPs), you can programmatically splice together function names on the fly, feed them straight into a templated wrapper, and keep your codebase DRY, even when library naming conventions aren’t friendly to templates.

This example demonstrates a compact metaprogramming pattern that glues together three C++ tools:

  1. The pre‑processor – builds identifiers by token‑pasting.
  2. Non‑Type Template Parameters (NTTP) – passes function pointers as template arguments.
  3. A thin forwarding class template – exposes the function behind the pointer.
//==================================================================================================
//  Example:  Generating Closely‑Related Classes with the Pre‑Processor and NTTPs                  //
//==================================================================================================

//---------------------------------------------
//  1.  Required headers                                                           
//---------------------------------------------
#include <iostream>

//---------------------------------------------
//  2.  Pre‑processor utilities                                                    
//---------------------------------------------
//
//  CONCAT() concatenates two tokens **at compile time**.  
//  `A ## B` literally glues A and B together before the compiler ever sees them.  
//  There is *no* runtime cost.
//
#define CONCAT(A, B) A ## B

//---------------------------------------------
//  3.  Library code we cannot change                                             
//---------------------------------------------
//
//  Imagine these free functions live inside a vendor library.  
//  Their names follow the pattern  <Category>FunctionOne().
//
int FooFunctionOne()
{
    return 1;
}

int BarFunctionOne()
{
    return -1;
}

//---------------------------------------------
//  4.  Generic wrapper driven by an NTTP                                          
//---------------------------------------------
//
//  ‑ `Func` is a **non‑type template parameter** holding a *function pointer*.  
//  ‑ At instantiation the compiler substitutes the pointer’s *value*, so calls are
//    resolved at compile time and inlined in practice.
//
template<int (*Func)()>
class UsesTemplates
{
public:
    int CallFunction()
    {
        return Func();    // always use braces                                   
    }
};

//---------------------------------------------
//  5.  Convenience macro for class instantiation                                  
//---------------------------------------------
//
//  ‑ The caller supplies a *category prefix* (Foo / Bar / …).  
//  ‑ CONCAT builds the required symbol name <Prefix>FunctionOne.  
//  ‑ The resulting token is fed to the template as a pointer.
//
//  Example:  TEMPLATE_CLASS(Foo) -> UsesTemplates<&FooFunctionOne>
//
#define TEMPLATE_CLASS(PREFIX) UsesTemplates<&CONCAT(PREFIX, FunctionOne)>

//---------------------------------------------
//  6.  Demonstration                                                              
//---------------------------------------------
int main()
{
    TEMPLATE_CLASS(Foo) fooClass;   // Expands to UsesTemplates<&FooFunctionOne>
    TEMPLATE_CLASS(Bar) barClass;   // Expands to UsesTemplates<&BarFunctionOne>

    const auto fooValue { fooClass.CallFunction() };
    const auto barValue { barClass.CallFunction() };

    std::cout << "Foo = " << fooValue << '\n';
    std::cout << "Bar = " << barValue << '\n';
    return 0;
}

When compiled, we can see the string substitution was successful:

UsesTemplates<&FooFunctionOne()>::CallFunction():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 8
        mov     QWORD PTR [rbp-8], rdi
        call    FooFunctionOne()
        leave
        ret


Token Pasting Metaprogramming: Key Take‑aways

This example demonstrates three key points about C++ template metaprogramming, specifically using NTTPs:

  • Token pasting (##) lets you compute identifiers using simple placeholders.
  • Mixing token pasting with NTTPs cleanly bridges “pre‑processor world” and “template world”.
  • The technique scales: add BazFunctionOne(), then use TEMPLATE_CLASS(Baz) – no new code.

C++ token pasting metaprogramming may seem like a niche technique, but it neatly bridges the gap between rigid third-party naming schemes and the type-safe elegance of modern templates. Master it once, and you can roll out families of boilerplate-free wrappers, reduce maintenance overhead, and keep your abstractions clean – precisely the kind of pragmatic win for solid C++ craftsmanship.

Want more C++ tips? Check out these posts:


Discover more from John Farrier

Subscribe to get the latest posts sent to your email.

Leave a Reply

Discover more from John Farrier

Subscribe now to keep reading and get access to the full archive.

Continue reading