2

Using functors with parameters generally looks like that:

// Definition:
struct some_functor_with_params
{
    int ref;
    explicit some_functor_with_params(int ref) : ref(ref) {}
    bool operator ()(int i) const {return i == ref;}
};

// Usage:
std::vector<int> v;
std::find_if(v.begin(), v.end(), some_functor_with_params(42));

For a functor without parameters, the code may become

// Definition:
struct some_functor_without_params
{
    bool operator ()(int i) const {return i == 42;}
};

// Usage:
std::vector<int> v;
std::find_if(v.begin(), v.end(), some_functor_without_params());

but I would prefer the following usage:

std::vector<int> v;
std::find_if(v.begin(), v.end(), some_functor_without_params); // no parens

which has the following advantages:

  • more concise
  • more readable when invoking the functor directly: some_functor_without_params(i) rather than some_functor_without_params()(i)
  • interchangeable with a function: bool some_functor_with_params(int i) {return i == 42;}

I implemented it the following way in a header file:

namespace {
    struct
    {
        bool operator ()(int i) const {return i == 42;}
    } some_functor_without_params;
}

I think the struct does not need a name since it has no user-declared constructor (nor destructor, nor anything requiring the struct name). I put the object in an unnamed namespace so that each compilation unit has its own some_functor_without_params and there is no 'double definition' link error.

Is there any performance penalty or any other drawback I cannot see?

This approach worked as expected until I encountered a very strange compilation error with Visual C++ 2013 which disappeared when naming the functor type, i.e. replacing

struct
{
    bool operator ()(int i) const {return i == 42;}
} some_functor_without_params;

with

struct some_functor_without_params_t
{
    bool operator ()(int i) const {return i == 42;}
} some_functor_without_params;

The error occurs only in Debug, not in Release, and states

error C2039: '<unnamed-type-some_functor_without_param>': is not a member of 'my_namespace:: ?? A0xbf2cc73f'

in file xstring, here:

_Myt& operator+=(const _Elem *_Ptr)
    {   // append [_Ptr, <null>) // <-- on this line(!)
    return (append(_Ptr));
    }

It looks like a compiler bug, what do you think?

  • Note that one important difference of your new approach is that you have only one global instance of the functor, while the first approach creates temporaries. (Sorry if you already knew this. It is important when the functor has a state.) – alain Jun 28 '17 at 16:26
  • 1
    An unnamed namespace should not be used in an header file as symbol are defined per compilation unit. – Phil1970 Jun 28 '17 at 16:40
  • @Phil1970 There are exceptions to this rule, c.f. Boost or STL placeholders like `_1`, `_2`, etc. Sometimes, having one symbol per compilation unit is what you want. – Christophe Fuzier Jun 28 '17 at 16:45

0 Answers0