лямбда как параметр шаблона с доступом к указателю 'this'? - PullRequest
0 голосов
/ 15 января 2012

Мне нужно создать объекты из трех-четырех классов, все унаследованные от одного базового класса, но некоторые объекты должны иметь различное поведение - например, полное изменение одной функции;Я могу сделать это с помощью большего количества наследования и полиморфизма, но это не кажется хорошей идеей.Мое первое решение состояло в том, чтобы использовать специализированные шаблоны (для каждого нестандартного случая), но затем я расскажу о лямбдах в качестве параметра шаблона (как здесь: Можем ли мы использовать лямбда-выражение в качестве значения по умолчанию для аргумента функции? ) и используйте их вместо метода класса (как здесь: C ++ 11 лямбда и специализация шаблонов ) - для меня это гораздо лучшее решение, потому что мне нужно только передавать лямбду для каждой странной ситуации:

auto default_lambda = [&]() -> int {return this->Sth;};
template<typename functor = decltype(default_lambda)>
class SomeClass{
...

Проблема с этим указателем - метод, который я хочу изменить, нуждается в доступе к нестатическим методам, а лямбда определяется вне нестатического метода.Более того, я не могу передать ссылку на класс лямбде, потому что это шаблонный класс (или, может, я ошибаюсь?).Конечно, я могу использовать специализированные шаблоны или просто указатели на функции, но мне действительно нравится решение с лямбдами, и я считаю, что оно гораздо лучше, чем другие мои идеи.Есть ли способ «избежать» этой проблемы?Или, может быть, моя идея была плохой все время?

Ответы [ 2 ]

2 голосов
/ 15 января 2012

В вашем подходе есть как минимум три очевидные проблемы:

  1. Класс SomeClass не получит доступ к закрытым членам, т. Е. Использование this исключено.
  2. Вы пытаетесь связать this из контекста, но нет контекста, т.е. ничего не связываете. Вам придется передать объект, чтобы иметь дело с параметром функции.
  3. Вы указали только тип объекта функции, но не экземпляр, т. Е. Вы не сможете использовать его позже.

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

struct default_lambda {
    template <typename T>
    int operator()(T const& o) const { return o.x(); }
};
template <typename F = default_lambda>
class SomeClass {
    ...
};
0 голосов
/ 01 марта 2012

Если вам нужно полное изменение одной функции, у вас есть два варианта:

  • Одна виртуальная функция, использующая, возможно, локальные классы + стирание типов, если у вас много таких объектов и вы не хотите создавать много типов областей пространства имен:
  • std::function, который можно отскочить позже, если хотите.

Пример кода для первого решения (вы даже можете сделать это шаблоном):

std::unique_ptr<my_base2> get_an_object()
{
    class impl : public my_base2
    {
        void my_virtual_function() { blah blah; }
    };

    return std::unique_ptr<my_base2>(new impl);
}

Обе обычно превосходят шаблоны в этой ситуации (но без контекста трудно сказать).

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