views:

54

answers:

1

I want to mock a method with the declaration A::B X(void). The definition is something as follows.

class A {
    class B;
    virtual B X() = 0;
};

class A::B {
  public:
    auto_ptr<int> something;
};

My mock class, following this, is quite standard.

class mA : public A
{
  public:
    MOCK_METHOD0(X, A::B());
};

Compiled, however, this gives me this weirdo error, and I haven't been able to track it down. What is wrong with this?

In member function ‘virtual A::B mA::X()’:
...: error: no matching function for call to ‘A::B::B(A::B)’
...: note: candidates are: A::B::B()
...:                       A::B::B(A::B&)

Update I have found a failing code sample to demonstrate this.

#include <gmock/gmock.h>
#include <memory>
using std::auto_ptr;

class thing {
  public:
    class result;
    virtual result accessor () = 0;
};

class thing::result {
    auto_ptr<int> x;   // If this just "int", error goes away.
};

namespace mock {
    class thing : ::thing {
      public:
        MOCK_METHOD0 ( accessor, result() );
    };
}
+3  A: 

It is hard to tell without the definitions of A and B. sounds like it is trying to construct a B from a temporary and failing because it can't bind the temporary to a non-const reference.

For example, your copy constructor might be defined as:

class A {
 public:
  class B {
   public:
    // This should be const, without good reason to make it otherwise.
    B(B&); 
  };
};

With the fix just making it a const reference.

Todd Gardner
Hmm, I don't define the copy constructor, but maybe... would this be affected by internal members of the class? `auto_ptr`, for instance?
Andres Jaan Tack
Absolutely, auto_ptr has a non-const copy constructor, and it forces B to have a non-const copy constructor.
Todd Gardner
As a fix, you should consider what you want to do with that pointer in the copying case; Use a shared pointer if want to the copy to share access between classes (probably only good if the pointed to object is immutable), or write your copy copy constructor that clones whatever the object (if they should both have their own), or make the object uncopyable and change around A's interface to pass around some handle to B instead.
Todd Gardner
Awesome! Thanks for clearing that up for me, dude.
Andres Jaan Tack