В чем смысл этого паттерна: использование структуры, содержащей один метод - PullRequest
8 голосов
/ 28 мая 2009

В нашем коде у нас довольно много случаев этого паттерна:

class outerClass
{
    struct innerStruct
    {
        wstring operator()( wstring value )
        {
            //do something
            return value;
        }
    };

    void doThing()
    {
        wstring initialValue;
        wstring finalValue = innerStruct()( initialValue );
    }
};

В чем преимущество этого:

class outerClass
{
    wstring changeString( wstring value )
    {
        //do something
        return value;
    }

    void doThing()
    {
        wstring initialValue;
        wstring finalValue = changeString( initialValue );
    }
};

Ответы [ 2 ]

16 голосов
/ 28 мая 2009

Структура с оператором () часто называется функтором, эффективно действующим как «объект функции». Вы можете использовать эти функторы со многими API, особенно STL, более легко и надежно, чем вы можете использовать типичные указатели функций. Функторы, являющиеся объектами, могут содержать состояние и параметризоваться во время построения для создания автономного специализированного обработчика.

Я предполагаю, что часто у вас есть код в externalClass, который хочет использовать эти библиотечные функции (т.е. std :: for_each), и поэтому разработал этот шаблон, чтобы сделать его тривиальным. Если вы никогда не используете функторы, тогда да, этот синтаксис бессмысленен и труден для чтения (и может быть заменен, как вы предлагаете).

Редактировать: Вам может понравиться Вопрос 317450 , об операторе ().

4 голосов
/ 28 мая 2009

Это шаг оптимизации для шаблонных предикатов.

Дело не в том, что функтор проще в использовании, чем функция. И то, и другое работает примерно одинаково в контексте boost и STL.

Чем они отличаются, это в шаблонах.

Представьте себе тривиальную шаблонную функцию, которая требует предикат

template< typename Predicate >
void  DoSomething( Predicate func )
{
  func();
}

Использование функции приведет к созданию экземпляра шаблона с указателем на функцию .

void changeString();

DoSomething( &changeString );

// This creates a template instantiation expecting a pointer to a function.
// The specific pointer may be evaluated at runtime.

// void DoSomething( void(func*)() );

Использование функтора создаст экземпляр экземпляра шаблона с определенным типом функтора .

struct changeString
{
    void operator() ();
}

DoSomething( changeString() );

// This creates a template instantiation expecting an instance of the struct.
// The exact function being called is now known at compile time.

// void DoSomething( changeString );

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

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