Adapter/Decorator pattern from "Hands-on Design Patterns with C++"
12:03 28 Apr 2026

I have the following classes adapted from the section "Adapter versus policy" page 515 of "Hands-on Design Patterns with C++":

  • a Value class with basic operations

  • decorators/adapters to make the underlying Value comparable with equality and/or addable.

All the template magic is needed because a class like Ordered>> needs to have operator+ returning Ordered>> and not just Addable>.

#include 

template 
class Value
{
public:
        using basic_type = T;
        using value_type = Value;
        template  using rebind = Value;

        explicit Value() = default;
        explicit Value(basic_type v) : m_val {v} {}
        Value(Value const&) = default;
        Value& operator=(Value const&) = default;
        Value& operator=(basic_type rhs) {
                m_val = rhs;
                return *this;
        }

        friend std::ostream& operator<<(std::ostream& out, Value x) {
                out << x.m_val;
                return out;
        }
protected:
        T m_val {};
};

template 
class Ordered : public T::template rebind
{
        using base_type = typename T::template rebind;
public:
        using base_type::base_type;
        using base_type::operator=;
        template  using rebind = Ordered;
        using value_type = typename base_type::value_type;
        using basic_type = typename value_type::basic_type;

        Ordered(value_type v) : base_type {v} {}
        bool operator==(FT rhs) {
                return this->m_val == rhs.m_val;
        }
        bool operator==(basic_type rhs) {
                return this->m_val < rhs;
        }
        friend bool operator==(basic_type lhs, FT rhs) {
                return rhs == lhs;
        }
};

template 
class Ordered : public T::template rebind>
{
        using base_type = typename T::template rebind;
public:
        using base_type::base_type;
        using base_type::operator=;
        template  using rebind = Ordered;
        using value_type = typename base_type::value_type;
        using basic_type = typename value_type::basic_type;

        Ordered(value_type v) : base_type {v} {}
        bool operator==(Ordered rhs) {
                return this->m_val == rhs.m_val;
        }
        bool operator==(basic_type rhs)
        {
                return this->m_val == rhs;
        }
        friend bool operator==(basic_type lhs, Ordered rhs)
        {
                return rhs == lhs;
        }
};

template 
class Addable : public T::template rebind
{
        using base_type = typename T::template rebind;
public:
        using base_type::base_type;
        using base_type::operator=;
        template  using rebind = Addable;
        using value_type = typename base_type::value_type;
        using basic_type = typename value_type::basic_type;

        Addable(value_type v) : base_type {v} {}
        FT operator+(FT rhs) {
                return FT {this->m_val + rhs.m_val};
        }
        FT operator+(basic_type rhs) {
                return FT {this->m_val + rhs};
        }
        friend FT operator+(basic_type lhs, FT rhs) {
                return rhs + lhs;
        }
};

template 
class Addable : public T::template rebind>
{
        using base_type = typename T::template rebind;
public:
        using base_type::base_type;
        using base_type::operator=;
        template  using rebind = Addable;
        using value_type = typename base_type::value_type;
        using basic_type = typename value_type::basic_type;

        Addable(value_type v) : T {v} {}
        Addable operator+(Addable rhs) {
                return Addable {this->m_val + rhs.m_val};
        }
        Addable operator+(basic_type rhs) {
                return Addable {this->m_val + rhs};
        }
        friend Addable  operator+(basic_type lhs, Addable rhs) {
                return Addable {lhs + rhs.m_val};
        }
};

The issue I'm observing is that compiling with GCC 15.2.1 with -std=c++20 and the following main:

int main()
{
        using Type = Addable>>;
        Type a {5}, b {3}, c{7};

        if (c + 1 == a + b) {
                std::cout << "equality" << std::endl;
        }
}

runs into the following warning:

adapter.cpp: In function ‘int main()’:
adapter.cpp:127:26: warning: C++20 says that these are ambiguous, even though the second is reversed:
  127 |         if (c + 1 == a + b) {
      |                          ^
adapter.cpp:40:14: note: candidate 1: ‘bool Ordered::operator==(FT) [with T = Value; FT = Addable > >]’
   40 |         bool operator==(FT rhs) {
      |              ^~~~~~~~
adapter.cpp:40:14: note: candidate 2: ‘bool Ordered::operator==(FT) [with T = Value; FT = Addable > >]’ (reversed)
    ~/Desktop/cpp_learning                                                                                                                             

Could you help me understand why that warning happens?

Btw, if the Type = Ordered>> in main, the code compiles without warning.

c++ templates adapter decorator