Переадресация вызовов функций на базовые данные в шаблоне оболочки - PullRequest
1 голос
/ 19 февраля 2020

Я пишу шаблонную оболочку, что-то вроде этого

template<class T>
class Wrapper{
public:
    Wrapper(T data);
    ~Wrapper();

    void doSomeWrapperWork();

private:
    T data;
};

Если я хочу получить доступ к упакованным данным, я, очевидно, могу добавить функцию получения, которая возвращает ссылку на данные. Однако мне было интересно, есть ли в любом случае, с некоторым шаблоном magi c, прямой вызов функций-оберток лежащих в основе упакованных данных. Другими словами, если у меня есть класс TestObject с функцией publi c void foo(), я хотел бы иметь возможность вызывать его следующим образом:

Wrapper<TestObject> myWrapper;
myWrapper.foo();

вместо:

myWrapper.getData().foo();

не зная априори, что такая функция существует. Это возможно?

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Да, попробуйте что-то вроде

#include <iostream>
struct TestObject{
    void foo() { std::cout << "TestObject" << std::endl;}
};

template <class T>
struct Wrapper : public T{
    Wrapper() {}
    void doSomeWrapperWork() {}
};

int main() {
    Wrapper<TestObject> wrapper;
    wrapper.foo();
}

Это позволяет вам добавлять дополнительные функции по мере необходимости, в то же время позволяя использовать оболочку в качестве класса T.

Это вдохновлено шаблон оформления декоратора.

1 голос
/ 19 февраля 2020

Не совсем, пока C ++ не получит отражение, мы не сможем легко написать классы-обертки без большого количества шаблонных макросов

, но

Вы можете добавить неявное преобразование ваш класс-обёртка T:

template<class T>
class Wrapper{
public:
    Wrapper(T data_) : data(data_) {}

    operator const T&() const
    {
        return data;
    }

private:
    T data;
};

А теперь ваш класс можно преобразовать в T, поэтому мы можем вызвать метод на T с небольшой работой:

использование:

struct Foo
{
    constexpr int bar() const
    {
        return 42;
    }
};

int main()
{
    constexpr Foo f;
    Wrapper<Foo> my_wrapper(f);
    static_assert(static_cast<const Foo&>(my_wrapper).bar() == 42);
}

Демо


Если вы хотите избежать кастинга самостоятельно, вы можете написать бесплатную функцию, которая будет вызывать вашу функцию, так что неявное преобразование может занять:

int call_bar(const Foo& f)
{
    return f.bar();
}

Использование:

Foo f;
Wrapper<Foo> my_wrapper(f);
std::cout << call_bar(my_wrapper); // 42

Demo2

Мне нравится этот подход, так как все, что требуется, это что мы добавляем бесплатную функцию для каждой обернутой функции, которую мы хотим, вместо того, чтобы вручную выполнять кучу приведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...