Neil Kirk
Neil Kirk

Reputation: 21803

Error compiling with std::not1 when unary_function uses reference argument

Here is my code:

using namespace std;

class Pixel
{
public:
    bool AreSamplesIdentical() const
    {
        return true;
    }
};

namespace
{
class Predicate_SamplesEqual : public unary_function<const Pixel&, bool>
{
public:
    bool operator () (const Pixel& pixel) const
    {
        return pixel.AreSamplesIdentical();
    }
};
}

int main()
{
    vector<Pixel> pixels(10);
    find_if(pixels.begin(), pixels.end(), not1(Predicate_SamplesEqual()));
}

On Visual Studio 2008 C++ Express, I get error: error C2529: '_Left' : reference to reference is illegal From inside library code.

But I tried here and it compiles: http://ideone.com/swWrZT

Who is wrong here? If me, how can I code a workaround?

The error occurs on the indicated line from functional

    // TEMPLATE CLASS unary_negate
template<class _Fn1>
    class unary_negate
    : public unary_function<typename _Fn1::argument_type, bool>
    {   // functor adapter !_Func(left)
public:
    explicit unary_negate(const _Fn1& _Func)
        : _Functor(_Func)
        {   // construct from functor
        }

    /**error**/bool operator()(const typename _Fn1::argument_type& _Left) const
        {   // apply functor to operand
        return (!_Functor(_Left));
        }

protected:
    _Fn1 _Functor;  // the functor to apply
    };

Upvotes: 3

Views: 606

Answers (2)

maverik
maverik

Reputation: 5606

I guess that error is due to unary_function that uses first template argument as a type and makes a reference:

template<typename Arg, typename Result>
struct unary_function
{
    typedef Arg argument_type;
    typedef Result result_type;
    ...
    virtual result_type operator()(const argument_type& _Left) const = 0;
    ...
}

So, if Arg is const X& then operator() uses const X& & - reference to reference, and vc 9.0 can't handle it.

The obvious fix is to write:

class Predicate_SamplesEqual : public unary_function<Pixel, bool>
...

Upvotes: 4

Steve Jessop
Steve Jessop

Reputation: 279345

Who is wrong here?

Neither MSVC nor GCC claims to conform to any standard when run with default options, so neither is exactly "wrong".

In this case, GCC 4.7 applies the C++11 reference-collapsing rules (which are also a GNU extension even without C++11 mode).

If you want GCC to conform to the previous standard, pass command-line option --std=c++98 and it will reject your code.

Upvotes: 1

Related Questions