google mock unable to mock a method with a templated argument - c++

I am not sure if what I am trying to do is possible, but I have a hard time with the compiler trying to mock a method which contains a templated reference parameter.
The interface (removed all irrelevant methods)
class iat_protocol
{
public:
virtual void get_available_operators(etl::vector<network_operator, 5>&) = 0;
};
My mock
class at_protocol_mock : public iat_protocol
{
public:
MOCK_METHOD((void), get_available_operators, (etl::vector<network_operator, 5>&), (override));
};
This results in
In file included from /home/bp/dev/unode/eclipse/thirdparty/googletest/googlemock/include/gmock/gmock-actions.h:145,
from /home/bp/dev/unode/eclipse/thirdparty/googletest/googlemock/include/gmock/gmock.h:57,
from ../tests/shared/hal/at/at_channel_tests.cpp:1: /home/bp/dev/unode/eclipse/unit_tests/tests/shared/hal/at/mocks/at_protocol_mock.hpp: In member function ‘testing::internal::MockSpec<void(etl::vector<iobox::hal::at::network_operator, 5>&)> iobox::hal::at_protocol_mock::gmock_get_available_operators(const testing::internal::WithoutMatchers&, testing::internal::Function<void(etl::vector<iobox::hal::at::network_operator, 5>&)>*) const’: /home/bp/dev/unode/eclipse/thirdparty/googletest/googlemock/include/gmock/gmock-function-mocker.h:343:74: error: invalid combination of multiple type-specifiers 343 | typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type
| ^~~~ /home/bp/dev/unode/eclipse/thirdparty/googletest/googlemock/include/gmock/internal/gmock-pp.h:17:31: note: in definition of macro ‘GMOCK_PP_IDENTITY’
My c++ skills are not good enough to have a clue what the compiler tries to tell me.
Who can help me ?

Well, this is strange, but simple using fixes your problem.
#include "gmock/gmock.h"
struct network_operator {};
namespace etl {
template <typename T, unsigned N>
struct vector {};
} // namespace etl
using vector_5 = etl::vector<network_operator, 5>;
class iat_protocol {
public:
virtual void get_available_operators(vector_5&) = 0;
};
class at_protocol_mock : public iat_protocol {
public:
MOCK_METHOD(void, get_available_operators,
(vector_5&),(override));
};
From gMock cookbook Dealing with unprotected commas

The latest gmock library shows the very more descriptive:
error: static_assert failed due to requirement '::testing::tuple_size<std::tuple<etl::vector<network_operator, 5> &>>::value == 2' "This method does not take 2 arguments. Parenthesize all types with unproctected commas."
MOCK_METHOD(void, get_available_operators,
Parenthesize all types with unproctected commas.
The other solution without using
#include "gmock/gmock.h"
struct network_operator {};
namespace etl {
template <typename T, unsigned N>
struct vector {};
} // namespace etl
using vector_5 = etl::vector<network_operator, 5>;
class iat_protocol {
public:
virtual void get_available_operators(etl::vector<network_operator, 5>&) = 0;
};
class at_protocol_mock : public iat_protocol {
public:
MOCK_METHOD(void, get_available_operators,
((etl::vector<network_operator, 5>&)), (override));
// ^ ^
};

Related

Initialization block to be run after constructors

Let's say I have the below class:
template <class Base>
struct Wrapper : public Base {
using Base::Base;
// ... add functionality ...
};
And I want some code to be executed during construction after constructors. I can't add a default constructor, because it won't be run when an inherited constructor is used. One idea is this:
template <class Base>
struct Wrapper : public Base {
bool _ = [this] {
// initialize ...
return true;
}();
using Base::Base;
};
This does work perfectly well as long as you place it as the last member, but it wastes memory.
Another way is:
#include <type_traits>
template <class T>
struct InitBlock {
InitBlock() {
static_cast<T*>(this)->init();
}
};
template <class Base>
struct Wrapper : public Base, private InitBlock<Wrapper<Base>> {
private:
template <class T>
friend struct InitBlock;
void init() {
// initialize ...
}
public:
using Base::Base;
};
Which is good, but a bit verbose. And there is nothing protecting init from being called again elsewhere. Also, if Wrapper adds members, this is called before those are initialized, so it's not ideal.
What is a better (safe and low on boilerplate) way of doing this?
As mentioned, we can use [[no_unique_address]] to avoid allocating memory for an empty class. It is honored by all major compilers, except for MSVC. MSVC has its own extension of [[msvc::no_unique_address]]. We wrap a macro around this, and it works fine:
#include <stdio.h>
#ifdef _MSC_VER
#define NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#else
#define NO_UNIQUE_ADDRESS [[no_unique_address]]
#endif
template <class Base>
struct Wrapper : public Base {
private:
NO_UNIQUE_ADDRESS struct Init {} _ = [] {
puts("Wrapper init");
return Init{};
}();
public:
using Base::Base;
};
struct Foo {
int i;
Foo(int i) : i(i) {
printf("Foo(%d)\n", i);
}
};
int main() {
Wrapper<Foo> wfoo(42);
Foo foo(43);
static_assert(sizeof(wfoo) == sizeof(foo));
}
You still have to take care to place it after all other members to make sure they're initialized by the time we touch them, so it's not ideal.
See online

C++ 'using' keyword in class hierarchy with function call operator and private inheritance

I have stumbled upon something that I don't quite understand. I have a class hierarchy that uses private inheritance where each of the structs defines a different function call operator. Oddly enough, the function call operator from the topmost struct is available in the most derived struct, despite the fact that a using directive is only used in the first derived struct. A regular function foo, though, is not accessible there, as expected. Example:
#include <string>
#include <vector>
#include <iostream>
struct A {
void foo() {}
void operator()(bool) {
std::cout << "bool\n";
}
};
struct B : private A {
using A::foo;
using A::operator();
void operator()(std::string) {}
};
struct C : private B {
using B::operator();
void operator()(std::vector<int>) {}
};
struct D : private C {
using C::operator();
void operator()(std::vector<double>) {}
};
int main() {
D d{};
d(false); // <-- works!
//d.foo(); // <-- error: ‘void A::foo()’ is private within this context
return 0;
}
I happened upon this while trying to implement the C++17 overload object for use with boost::apply_visitor using pre-C++17 code. I solved it using recursive inheritance, where each object pulls in the function call operator of its direct base class like so:
template<typename T, typename... Ts>
struct visitor : private T, private visitor<Ts...> {
using T::operator();
using visitor<Ts...>::operator();
visitor(T func, Ts... tail) : T{ std::move(func) }, visitor<Ts...>{ std::move(tail)... } {}
};
template<typename T>
struct visitor<T> : private T {
using T::operator();
visitor(T func) : T{ std::move(func) } {}
};
template<typename... Ts>
visitor<Ts...> make_visitor(Ts&&... funcs) {
return visitor<Ts...>{ std::forward<Ts>(funcs)... };
}
I wanted to understand why all of the operators are available in the most derived object. That's how I came up with the above example. Compiler is g++ 11.1.0.
Can anyone enlighten me as to what's going on here?
As pointed out by others in comments, it turns out I just had an error in my thinking. The using pulls in all the operators available in the respective base class, including the ones that were imported by the base class itself, and therefore all the operators will be available in the bottommost object. foo, on the other hand, is just handed down to B.

Extend a template classe using the type definition in subclass

I imitated the std::enable_shared_from_this to create a template class, but I made the class use the type definition in its subclass.
Unfortunately!
Although I used typename, after compiling,
//
// https://ideone.com/eYCBHW http://ideone.com/eYCBHW
#include <iostream>
#include <set>
#include <map>
using namespace std;
template<class _S> struct A {
};
template<class _Subclass>
class Global {
public:
typedef typename _Subclass::connection_t connection_t;
//std::map<std::string, _Subclass::connection_t> connections;
//std::set<_Subclass::connection_t> connections;
//using typename _Subclass::connection_t;
//typename _Subclass::connection_t* connections;
//connection_t* connections;
};
class CConnection {};
class SConnection;
class Client : public Global<Client> {
public:
typedef CConnection connection_t;
};
#if 0
class Server : public Global<Server> {
public:
typedef SConnection connection_t;
};
#endif
class SConnection {};
int main() {
// your code goes here
return 0;
}
GCC complained:
prog.cpp: In instantiation of ‘class Global<Client>’:
prog.cpp:25:23: required from here
prog.cpp:14:43: error: invalid use of incomplete type ‘class Client’
typedef typename _Subclass::connection_t connection_t;
^~~~~~~~~~~~
prog.cpp:25:7: note: forward declaration of ‘class Client’
class Client : public Global<Client> {
^~~~~~
How to solve it?
References
Where and why do I have to put the “template” and “typename” keywords?
C++ - meaning of a statement combining typedef and typename [duplicate]
Two template classes use each other as template argument
Having a typedef at class level requires the template arguments to be complete types. How would the compiler otherwise be able to check, if the type provided as argument actually has some equivalent typedef itself?
Analogously, the following is going to fail:
class C;
using G = Global<C>; // C is not a complete type!
class C // too late...
{
// ...
};
Problem with curiously recurring template pattern, which is what you're trying to implement, that at the point you try to derive, the class is not yet complete, just as in my example above:
class Client : public Global<Client> // client is not yet complete!
{
}; // only HERE, it will get complete, but that's too late for above
Ever wondered, though, why member variables are known within member functions even though being declared after the function? That's because
class C
{
void f() { n = 12; }
int n = 10;
};
is compiled as if it was written as:
class C
{
inline void f();
int n = 10;
};
void C::f() { n = 12; } // n is known now!
This is at the same time the clue where you can use the template argument the way you intend:
template<class T> // different name used! *)
class Global
{
public:
void f()
{
typedef typename T::connection_t connection_t; // possible here!
// (similar to why you can use the static cast as in the link provided)
}
};
That won't help, though, with your members:
std::map<std::string, typename T::connection_t> connections;
// ^ additionally was missing, but won't help either
T still remains incomplete at this point.
Within the comments, though, you only seem to use the connection type. If you don't need the client or server class for any reason other than the typedef, you can solve the issue pretty simply:
template<class T> // different name used! *)
class Global
{
std::map<std::string, T> connections;
// ^ use T directly
};
class Client : public Global<CConnection>
// ^ make sure it is defined BEFORE
{
// ...
};
Otherwise, you need to fall back to other means, e. g. the pimpl pattern, where you would let the implementation class inherit from the template.
*) Identifiers starting with underscore followed by captial letter, as well as those containing two subsequent identifiers, are reserved for the implementation (i. e. for use by the compiler). Defining your own such ones yields undefined behaviour.
Edit (stolen from the comments):
If you need client or server from within Global, you could provide both as separate template paramters as well:
template <typename Base, typename Connection>
{
// use Connection directly, e. g. for member definitions
// and Base within member functions as mandated by CRTP
};
class Client : public Global<Client, CConnection>
{ /* ... */ };

c++ inheritance and templates not compiling

I am trying to implement a generic hashlist class using templates and I am trying to inherit from the base class but getting lots of compile errors. Here is my code:
#ifndef BASEHASHLIST_H_
#define BASEHASHLIST_H_
#include <string>
#include <boost/unordered_set.hpp>
#include <iostream>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
template <typename T>
class BaseHashList
{
private:
boost::interprocess::interprocess_semaphore m_semaphore;
protected:
boost::unordered_set<T> m_hsHashSet;
typename boost::unordered_set<T>::iterator m_hsIter;
public:
BaseHashList();
};
template <typename T>
BaseHashList<T>::BaseHashList():m_semaphore(1){}
#endif /* BASEHASHLIST_H_ */
And here is the class that is inheriting from the base class:
#ifndef ACCOUNTLIST_H_
#define ACCOUNTLIST_H_
#include "BaseHashList.h"
class AccountList : public BaseHashList<unsigned long>
{
public:
AccountList(std::string p_strFile, unsigned long p_ulMaxAccountNo);
~AccountList(void);
int m_iVersion;
std::string m_strFilePath;
private:
unsigned long m_ulMaxAccountNo;
};
#endif /* ACCOUNTLIST_H_ */
and here is the cpp file:
#include "AccountList.h"
AccountList::AccountList(std::string p_strFile, unsigned long p_ulMaxAccountNo)
: BaseHashList<unsigned long>::m_hsHashSet<unsigned long>(),
m_iVersion(0),
m_strFilePath(p_strFile)
{
m_ulMaxAccountNo = p_ulMaxAccountNo;
}
AccountList::~AccountList(){}
I am receiving a lot of compile time errors such as:
expected template-name before token '<'
expected '(' before token '<'
For such a simple task I spent couple of hours and I am super frustrated, does anybody see what I am doing wrong here?
This initaliser in AccountList's constructor looks wrong to me:
BaseHashList<unsigned long>::m_hsHashSet<unsigned long>()
You should initalise the members of BaseHashList inside a constructor of BaseHashList itself, one will always either explicitly or implicitly be called.
This example is simplified and similarly wrong:
struct A {
int bar;
};
struct B : A {
B() : A::bar(0) {}
};
(saying bar(0) would also be wrong there)
However you can get the desired behaviour:
struct A {
A() : bar(0) {}
int bar;
};
struct B : A {
B() {} // Implicitly calls A::A although we could have explicitly called it
};
The constructor of A gets called and given a chance to initalise its members here still.
When you inherit from a template class, you have to add the template instruction to the child class too :
template <typename T>
class A : public B<T>
You also have to add the template instruction before the definition of constructors and methods :
template <typename T>
A<T>::A() : B<T>() {...}
template <typename T>
A<T>::~A() {...}

Two-phase lookup: can I avoid "code bloat"?

Two-phase lookup question:
Is there a more synthetic way to write this code, i.e. avoiding all those using directives?
Something like using CBase<T>; is what I would like, but it is not accepted.
#include <iostream>
template <typename T>
class CBase
{
protected:
int a, b, c, d; // many more...
public:
CBase() {
a = 123; c = 0;
}
};
template <typename T>
class CDer : public CBase<T>
{
// using CBase<T>; // error, but this is what I would like
using CBase<T>::a;
using CBase<T>::b;
//...
public:
CDer() {
std::cout << a << this->c;
}
};
int main()
{
CDer<int> cd;
}
In my real code there are many more member variables/functions, and I was wondering if it is possible to write shorter code in some way.
Of course, using the this->c syntax does not solve the problem...
Thank's!
gcc 4.1
MacOS X 10.6
I reduced the testcase and then consider three options
template<typename T> struct Base { int a; };
Option 1
template<typename T> struct Der : Base<T> {
void f() {
int &ra = Der::a;
// now use ra
}
}
Option 2
template<typename T> struct Der : Base<T> {
void f() {
// use this->a instead
// or Der::a
}
}
Option 3
// use your using declarations
It doesn't look like most of those variables are parameterized. Does CBase use them all, or just a? If not, move them into a new non-template base of CDer.
Or, pack them all into a POD struct and then using CBase<T>::m_ints;.
High overhead solution: non-templated virtual base.
Not sure but worth a try: nest the definition of CDer inside CBase and then typedef it into namespace scope.