[googlemock: 825] SetArgReferee requires redundant copy constructor?

1,055 views
Skip to first unread message

ospec

unread,
May 24, 2010, 10:43:00 AM5/24/10
to Google C++ Mocking Framework
In order to set an argument by reference I need to create a copy
constructor even though it is not needed by the actual code. I do not
want to add the redundant copy constructor. Am I doing something
wrong?

Here is the issue: Consider:
class ClassToMock {
public:
virtual void testMethod(SomeClass& a) {
SomeClass b;
a= b;
}

};

class MockedA : public ClassToMock
{
public:
MOCK_METHOD1(testMethod, void(SomeClass&));

};

The following piece of code does not compile:
SomeClass x;
EXPECT_CALL(mock, testMethod(_)).WillOnce(SetArgReferee<0>(x));

But instead compiler throws:
third_party\gmock-1.5.0\include\gmock\gmock-more-actions.h(160) :
error C2664:
'testing::SetArgRefereeActionP<k,value_type>::gmock_Impl<F>::gmock_Impl(value_type)' :
cannot convert parameter 1 from 'const SomeClass' to 'SomeClass'
1> with
1> [
1> k=0,
1> value_type=SomeClass,
1> F=void (SomeClass &)
1> ]
1> Cannot copy construct class 'SomeClass' due to ambiguous
copy constructors or no available copy constructor

mytestcase.cpp(100) : see reference to function template instantiation
'testing::SetArgRefereeActionP<k,value_type>::operator
testing::Action<F>(void) const<F>' being compiled
1> with
1> [
1> k=0,
1> value_type=SomeClass,
1> F=void (SomeClass &)
1> ]

Vlad Losev

unread,
May 25, 2010, 2:18:11 PM5/25/10
to Google C++ Mocking Framework, Zhanyong Wan
Hi,
This appears to be an artifact of the action implementation. It was not detected previously because having a class with an assignment operator but without a copy constructor is highly unusual, and we never tested SetArgReferee with such a class. I have added issue 112 to track this.

- Vlad

Zhanyong Wan (λx.x x)

unread,
May 25, 2010, 8:00:07 PM5/25/10
to Vlad Losev, Google C++ Mocking Framework

This is actually the intended behavior. The action needs to save a
copy of the argument (hence needing the copy ctor) s.t. it's still
valid even if the original object has been modified or even died (e.g.
the argument may be a temporary object).

If a class supports =, it should probably have a copy ctor too.
Disabling the copy ctor doesn't buy you much, as someone can always
write:

SomeClass x;
x = foo;

as a workaround for

SomeClass x(foo);

If you really, really cannot give SomeClass a copy ctor, it's easy to
define a custom action for your purpose:

ACTION(CopyToArg0, from) { arg0 = *from; }

...
...WillOnce(CopyToArg0(&x));

--
Zhanyong

ospec

unread,
May 26, 2010, 1:00:17 AM5/26/10
to Google C++ Mocking Framework
Actually there is a simple and documented solution which I missed when
I wrote this post: wrap the argument with ByRef().
Thanks all,
Omri.

On May 26, 3:00 am, Zhanyong Wan (λx.x x) <w...@google.com> wrote:


> On Tue, May 25, 2010 at 11:18 AM, Vlad Losev <v...@losev.com> wrote:
> > Hi,

Reply all
Reply to author
Forward
0 new messages