Strange gmock compile error when using a forward declared class.

1,939 views
Skip to first unread message

Mike

unread,
Mar 18, 2010, 1:13:00 PM3/18/10
to Google C++ Mocking Framework, melind...@honeywell.com, robert...@honeywell.com
I have a header file similar to the one below:
------------------------------------------------------------------------------------------------------------------------------
#ifndef FOO_H_
#define FOO_H_

#include "gmock/gmock.h"

namespace app
{

// Forward declare of class used in Foo by reference, i.e. don't need
to
// include Bar.h
class Bar;

#ifdef UNIT_TEST
namespace mock
{
// The mock class.
class Foo
{
public:
MOCK_METHOD1(fooBar, void (const Bar&));
};
}
#endif

// The real class.
class Foo
{
public:
Foo();
virtual ~Foo();

void fooBar(const Bar&)
{
}
};

}

#endif // FOO_H_
------------------------------------------------------------------------------------------------------------------------------

Note the forward declared class Bar used by reference in the mock::Foo
class' interface. This technique is considered a good C++ programming
practice to avoid header file dependencies.

If you include the Foo.h in an empty Foo.cpp and compile it with

g++ -c Foo.cpp -I <gmock-incdir> -D UNIT_TEST

you get the following syntax errors about class Bar:

/home/e477610/vobs-tool/include/gmock/gmock-printers.h: In static
member function 'static void
testing::internal2::TypeWithoutFormatter<T,
kIsProto>::PrintValue(const T&, std::ostream*) [with T = app::Bar,
bool kIsProto = false]':
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:178:
instantiated from 'std::basic_ostream<_CharT, _Traits>&
testing::internal2::operator<<(std::basic_ostream<_CharT, _Traits>&,
const T&) [with Char = char, CharTraits = std::char_traits<char>, T =
app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:220:
instantiated from 'void
testing_internal::DefaultPrintNonContainerTo(const T&, std::ostream*)
[with T = app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:299:
instantiated from 'void
testing::internal::DefaultPrintTo(testing::internal::IsNotContainer,
testing::internal::false_type, const T&, std::ostream*) [with T =
app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:337:
instantiated from 'void testing::internal::PrintTo(const T&,
std::ostream*) [with T = app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:547:
instantiated from 'static void
testing::internal::UniversalPrinter<T>::Print(const T&, std::ostream*)
[with T = const app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:610:
instantiated from 'static void
testing::internal::UniversalPrinter<T&>::Print(const T&,
std::ostream*) [with T = const app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:689:
instantiated from 'static void
testing::internal::TuplePrefixPrinter<N>::PrintPrefixTo(const Tuple&,
std::ostream*) [with Tuple = std::tr1::tuple<const app::Bar&,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass>,
unsigned int N = 1u]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:698:
instantiated from 'void testing::internal::PrintTupleTo(const T&,
std::ostream*) [with T = std::tr1::tuple<const app::Bar&,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass>]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:453:
instantiated from 'void testing::internal::PrintTo(const
std::tr1::tuple<_T1, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass>&, std::ostream*) [with T1 = const app::Bar&]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:547:
instantiated from 'static void
testing::internal::UniversalPrinter<T>::Print(const T&, std::ostream*)
[with T = std::tr1::tuple<const app::Bar&, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass>]'
/home/e477610/vobs-tool/include/gmock/gmock-spec-builders.h:1779:
instantiated from 'typename testing::internal::Function<F>::Result
testing::internal::FunctionMockerBase<F>::InvokeWith(const typename
testing::internal::Function<F>::ArgumentTuple&) [with F = void ()
(const app::Bar&)]'
/home/e477610/vobs-tool/include/gmock/gmock-generated-function-
mockers.h:95: instantiated from 'R
testing::internal::FunctionMocker<R ()(A1)>::Invoke(A1) [with R =
void, A1 = const app::Bar&]'
../Foo.h:20: instantiated from here
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:130: error:
invalid application of 'sizeof' to incomplete type 'const app::Bar'
[mcox_incr2_view] e477610@pepe2 ~/workspace/psmrs/default/gmock-error/
Debug
$ clear
[mcox_incr2_view] e477610@pepe2 ~/workspace/psmrs/default/gmock-error/
Debug
$ clear;g++ -c ../Foo.cpp -I /home/e477610/vobs-tool/include -D
UNIT_TEST
/home/e477610/vobs-tool/include/gmock/gmock-printers.h: In static
member function 'static void
testing::internal2::TypeWithoutFormatter<T,
kIsProto>::PrintValue(const T&, std::ostream*) [with T = app::Bar,
bool kIsProto = false]':
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:178:
instantiated from 'std::basic_ostream<_CharT, _Traits>&
testing::internal2::operator<<(std::basic_ostream<_CharT, _Traits>&,
const T&) [with Char = char, CharTraits = std::char_traits<char>, T =
app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:220:
instantiated from 'void
testing_internal::DefaultPrintNonContainerTo(const T&, std::ostream*)
[with T = app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:299:
instantiated from 'void
testing::internal::DefaultPrintTo(testing::internal::IsNotContainer,
testing::internal::false_type, const T&, std::ostream*) [with T =
app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:337:
instantiated from 'void testing::internal::PrintTo(const T&,
std::ostream*) [with T = app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:547:
instantiated from 'static void
testing::internal::UniversalPrinter<T>::Print(const T&, std::ostream*)
[with T = const app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:610:
instantiated from 'static void
testing::internal::UniversalPrinter<T&>::Print(const T&,
std::ostream*) [with T = const app::Bar]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:689:
instantiated from 'static void
testing::internal::TuplePrefixPrinter<N>::PrintPrefixTo(const Tuple&,
std::ostream*) [with Tuple = std::tr1::tuple<const app::Bar&,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass>,
unsigned int N = 1u]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:698:
instantiated from 'void testing::internal::PrintTupleTo(const T&,
std::ostream*) [with T = std::tr1::tuple<const app::Bar&,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass>]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:453:
instantiated from 'void testing::internal::PrintTo(const
std::tr1::tuple<_T1, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass>&, std::ostream*) [with T1 = const app::Bar&]'
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:547:
instantiated from 'static void
testing::internal::UniversalPrinter<T>::Print(const T&, std::ostream*)
[with T = std::tr1::tuple<const app::Bar&, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass, std::tr1::_NullClass,
std::tr1::_NullClass, std::tr1::_NullClass>]'
/home/e477610/vobs-tool/include/gmock/gmock-spec-builders.h:1779:
instantiated from 'typename testing::internal::Function<F>::Result
testing::internal::FunctionMockerBase<F>::InvokeWith(const typename
testing::internal::Function<F>::ArgumentTuple&) [with F = void ()
(const app::Bar&)]'
/home/e477610/vobs-tool/include/gmock/gmock-generated-function-
mockers.h:95: instantiated from 'R
testing::internal::FunctionMocker<R ()(A1)>::Invoke(A1) [with R =
void, A1 = const app::Bar&]'
../Foo.h:20: instantiated from here
/home/e477610/vobs-tool/include/gmock/gmock-printers.h:130: error:
invalid application of 'sizeof' to incomplete type 'const app::Bar'

Something is causing a method in template class
TypeWithoutFormatter<T, bool kIsProto>::PrintValue(const T&
value, ::std::ostream* os) to be instantiated and I'm not sure why.
Is there any way to work-around this issue?

Mike

Mike

unread,
Mar 18, 2010, 2:00:01 PM3/18/10
to Google C++ Mocking Framework
"Read the source, Luke." (the gmock-printers.h is *well* commented
with very useful hints).

Answering my own question :-$

It you add a declaration for PrintTo() in the same namespace as Bar in
your mock code, the compiler will not instantiate any of the gmock
printers plumbing (see below). Of course you have actually define it
somewhere.

Mike

On Mar 18, 11:13 am, Mike <mh...@bluezoosoftware.com> wrote:
> I have a header file similar to the one below:
> ------------------------------------------------------------------------------------------------------------------------------
> #ifndef FOO_H_
> #define FOO_H_
>
> #include "gmock/gmock.h"
>
> namespace app
> {
>
> // Forward declare of class used in Foo by reference, i.e. don't need
> to
> // include Bar.h
> class Bar;
>
> #ifdef UNIT_TEST

void PrintTo(const Bar&, std::ostream *);

Bruce Trask

unread,
Mar 20, 2010, 1:53:18 PM3/20/10
to Google C++ Mocking Framework
Hello,

Were there plans to open source the pump script?

Regards,
Bruce

Zhanyong Wan (λx.x x)

unread,
Mar 20, 2010, 7:38:39 PM3/20/10
to Bruce Trask, Google C++ Mocking Framework, Google C++ Testing Framework
(+googletestframework)

Hi Bruce,

On Sat, Mar 20, 2010 at 10:53 AM, Bruce Trask
<bruce...@mdesystems.com> wrote:
> Hello,
>
> Were there plans to open source the pump script?

Yes, but it kept being bumped off the table as no one has asked for
it. We'll probably add it to the gtest distribution, as it's used
there too.

The script is quite usable, but not polished yet. Nor does it have
tests. I think I'll just publish it as is and hope that someone will
add the final touch later.

I'm curious on what you plan to use it for and when you need it. Thanks,

> Regards,
> Bruce

--
Zhanyong

Bruce Trask

unread,
Mar 21, 2010, 7:40:49 PM3/21/10
to Zhanyong Wan (λx.x x), Google C++ Mocking Framework, Google C++ Testing Framework
Hi Zhanyong,

> I'm curious on what you plan to use it for and when you need it.

Our interest is based on a query I made a while ago and one of your suggested possible solutions.

http://groups.google.com/group/googletestframework/tree/browse_frm/month/2009-01/efeedefed48eef85?rnum=81&_done=%2Fgroup%2Fgoogletestframework%2Fbrowse_frm%2Fmonth%2F2009-01%3F

We are very interested in various meta-programming languages.

>The script is quite usable, but not polished yet. Nor does it have
>tests. I think I'll just publish it as is and hope that someone will
>add the final touch later.

Sounds good. We'll take anything you've got as soon as you have time to make it available. No polish needed. Would love to try it out for what we are trying to do.

Thanks in advance.

Regards,
Bruce

Zhanyong Wan (λx.x x)

unread,
Mar 22, 2010, 5:14:11 PM3/22/10
to Bruce Trask, Google C++ Mocking Framework, Google C++ Testing Framework
I have published the Pump user's manual at
http://code.google.com/p/googletest/wiki/PumpManual - will add the
script to SVN soon. Thanks,

2010/3/21 Bruce Trask <bruce...@mdesystems.com>:

> To unsubscribe from this group, send email to googletestframework+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>

--
Zhanyong

Zhanyong Wan (λx.x x)

unread,
Mar 23, 2010, 3:23:43 AM3/23/10
to Bruce Trask, Google C++ Mocking Framework, Google C++ Testing Framework
The pump script was committed to the SVN trunk in r400. Cheers,

2010/3/22 Zhanyong Wan (λx.x x) <w...@google.com>:

--
Zhanyong

Bruce Trask

unread,
Mar 23, 2010, 1:18:35 PM3/23/10
to Zhanyong Wan (λx.x x), Google C++ Mocking Framework, Google C++ Testing Framework
Thanks Zhanyong.
Reply all
Reply to author
Forward
0 new messages