tags:

views:

290

answers:

2

In our code we have quite a few cases of this pattern:

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

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

What's the advantage of this over:

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

    void doThing()
    {
        wstring initialValue;
        wstring finalValue = changeString( initialValue );
    }
};
+15  A: 

A struct with an operator() is often called a functor, effectively acting as a "Function object". You can use these functors with many APIs, especially the STL, more easily and robustly than you can use typical function pointers. Functors being objects, they can contain state, and be parameterised during construction to create a self contained specialised handler.

I presume that often times, you have code in outerClass that wants to use these library functions (i.e. std::for_each), and so have developed this pattern to make it trivial. If you never use functors, then yes, this syntax is pointless and hard to read (and can be replaced as you suggest).

Edit: You might like Question 317450, about operator().

Adam Wright
Aha that makes sense thanks! I think in some places it's for that reason, but in others it's just copied across (the pattern, not the code).
Ant
+2  A: 

It's an optimization step for templated predicates.

It's not a matter of a functor being easier to use than a function. Both work pretty much the same way in boost and STL contexts.

How they differ is in template instantiation.

Imagine a trivial template function that requires a predicate

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

Using a function will instantiate a template instance with a function pointer.

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*)() );

Using a functor will instantiate a template instance with a specific functor type.

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 );

With the functor, the specific functionality is now well defined and the struct being passed in is likely not used and can be optimized out.

Shmoopty
Very clear thanks.
Ant