Расширение типа в С++

К сожалению, UFCS не попал в С++ 17, и это оставило меня с повторяющейся проблемой: Иногда я хочу предоставить дополнительные возможности типов, используя синтаксис вызова метода (без написания глобальных функций). Это особенно удобно при работе с монадами.

Я вижу два варианта: одно - наследование, а другое - инкапсуляция. Поскольку вы не можете безопасно наследовать от контейнеров STL, это оставляет инкапсуляцию. Например, я хочу расширить std::optional, поэтому пишу:

template <typename T>
struct myoption {
    // Some functionality
private:
    std::optional<T> impl;
};

Моя проблема в том, что каждый раз, когда я хочу это сделать, я в основном должен писать все конструкторы (и необходимые методы, которые вы можете использовать с исходным типом, например push_back для векторов), который имеет исходный тип. Даже более простой контейнер, как и факультативный, имеет 9 конструкторов. При использовании наследования я могу просто "наследовать" методы и конструкторы суперкласса. Есть ли способ сделать это проще с помощью инкапсуляции?

Ответ 1

Я бы реализовал его, используя личное наследование:

#define MAKE_PUBLIC(method) using std::vector<T>::method

template <typename T>
struct My_vector : private std::vector<T> {
    MAKE_PUBLIC(push_back);
    MAKE_PUBLIC(pop_back);
};

int main() {
    My_vector<int> v;
    v.push_back(3);
    std::vector<int>* vec = new My_vector<int>; // won't compile
}

Таким образом, вы можете не создавать объекты с типом dynamic My_vector и уменьшать усилия, чтобы сделать унаследованные методы доступными простым макросом (или с помощью директивы) вместо создания вперед функции для каждой функции-члена и перегрузки.