The policy is a C++ template-based design pattern to customize the behavior of a template class. The idea is using compile-time templates to choose the Policies provided by the class. Apparently, this has better performance than using virtual functions and provides better safety as it depends on compile-time checking.

For example, the host class ParserManager can use either XML or JSON parser using templates ParserManager<XMLParserPolicy> xmlParser;. The policy classes implement doParse.

#include <iostream>
#include <string>

using namespace std;

template <class ParserPolicy>
class ParserManager : public ParserPolicy
{
public:
    ParserManager() = default;
    ~ParserManager() = default;

    void parse(const std::string &input)
    {
        this->doParse(input);
    }
};

class XMLParserPolicy
{
public:
    void doParse(const std::string &input)
    {
        // XML parsing logic
        std::cout << "Parsing XML: " << input << std::endl;
    }
};
class JSONParserPolicy
{
public:
    void doParse(const std::string &input)
    {
        // JSON parsing logic
        std::cout << "Parsing JSON: " << input << std::endl;
    }
};
int main()
{
    ParserManager<XMLParserPolicy> xmlParser;
    xmlParser.parse("<xml>data</xml>");

    ParserManager<JSONParserPolicy> jsonParser;
    jsonParser.parse("{\"key\": \"value\"}");

    return 0;
}

I think the most important advantage here is we can compose and customize behavior independently by using different policies for different things. For example, we can have policies for validation and parsing and implement several policy classes for each.

#include <iostream>
#include <string>

using namespace std;

template <class ParserPolicy, class ValidationPolicy>
class ParserManager : public ParserPolicy, ValidationPolicy
{
public:
    ParserManager() = default;
    ~ParserManager() = default;

    void parse(const std::string &input)
    {
        ValidationPolicy::validate(input);
        ParserPolicy::parse(input);
    }
};

class XMLParserPolicy
{
public:
    static void parse(const std::string &input)
    {
        // XML parsing logic
        std::cout << "Parsing XML: " << input << std::endl;
    }
};

class SimpleValidationPolicy
{
public:
    static void validate(const std::string &input)
    {
        // Simple validation logic
        if (input.empty())
        {
            throw std::invalid_argument("Input cannot be empty");
        }
        std::cout << "Input is valid." << std::endl;
    }
};

int main()
{
    ParserManager<XMLParserPolicy, SimpleValidationPolicy> xmlParser;
    xmlParser.parse("<xml>data</xml>");

    return 0;
}