How to use gmock to mock a template method (not a template class) for a class? Example a class like this, I want to mock this class, and this template method..
class A{
public:
template<EnumType ENUM_VALUE>
int getType(int val);
};
I know how to mock a class with non-virtual methods, or mock a templated class, but i dont know how to mock a non-templated class with a templated method..
First much better solution is to use the implementation of this function A::getType - maybe it does not have to be mocked? E.g.: if it just returns some value that is set in constructor - then just construct A in the way that is needed in your test case:
class A{
public:
A(int a) : a(a) {}
template<typename T>
int getType(int val)
{
return a + val;
}
private:
int a;
};
TEST(...)
{
A a(TYPE_VALUE_FOR_TEST);
...
}
If it cannot be done that way - then you might consider to have some instrumentation for UT that is switched with preprocessor macros:
#ifdef TESTING
namespace Testing
{
using std::pair<std::type_index, int> AGetTypeKey;
std::map<AGetTypeKey, int> AGetTypeExpectedValues;
template <typename T>
void expectAGetType(int inputValue, int expectedResult)
{
AGetTypeExpectedValues[AGetTypeKey(std::type_index(typeid(T)), inputValue)] = expectedResult;
}
template <typename T>
int getAGetType(int value)
{
return AGetTypeExpectedValues[AGetTypeKey(std::type_index(typeid(T)), inputValue)];
}
}
#endif
class A{
public:
A(int a) : a(a) {}
template<typename T>
int getType(int val)
{
#if TESTING
return Testing::getAGetType<T>(val);
#else
// your "normal" implementation
...
#endif
}
private:
int a;
};
// compiled with -DTESTING=1
#ifndef TESTING
#error ...
#endif
TEST(...)
{
Testing::expectAGetType<float>(EXPECTED_INPUT_VALUE,
TYPE_VALUE_FOR_FLOAT);
...
}
Regarding point-2 - of course all testing code should be carefully separated from "normal code" - e.g. in some separated header files.
It is worth to say that none of these solution is perfect - and this second solution might not be 100% reliable as you would test not real code but some testable version of it.
Maybe you should start from rethinking your design - as it seems the design was not completed with "design for testability" in mind.
I end up doing a relay to mock the method
E.g.
class MOCK_A{
public:
template<Enum ENUM_VALUE>
int getType(int val){
getType(val, ENUM_VALUE);
}
MOCK_METHOD1(getType, int(int val, Enum enum_value));
};
Related
I have an application class that can take in a dependent class as a template argument to the constructor. This dependent class is required to provide certain templated functions that the application class can call. I would like to offload this dependent class object to a pimpl class so the application class is not a template class and thus header-only.
Here is a rough idea of what I mean.
///////////
// impl.h
///////////
template<typename Helper>
struct Impl
{
public:
Impl(Helper& helper) : helper_(helper)
{
}
template <typename T>
void someHelperFn1(T t)
{
helper_->fn1(t);
}
template <typename U>
SomeOtherClass<U> someHelperFn2()
{
return helper_->fn2();
}
private:
Helper& helper_;
};
///////////
// app.h
///////////
#include "impl.h"
class App
{
public:
template<typename Helper>
App(Helper &h) :impl_(new Impl) {}
template <typename T>
void someHelperFn1(T t)
{
impl_->someHelperFn1(t);
}
template <typename U>
SomeOtherClass<U> someHelperFn2()
{
return impl_->someHelperFn2();
}
void someAppFn();
private;
std::unique_ptr<Impl> impl_;
};
///////////
// app.cpp
///////////
void App::someAppFn()
{
// some useful code
}
I realize the above code doesn't compile since Impl is really a template class and so App would also be a template class too. That is what I would like to avoid so that App is not a header-only class. I found something similar except the functions that I want to call from the helper dependency are template functions and they are not in this case. It seemed pretty close otherwise to what I wanted to do.
Any ideas on how I can avoid making App a template class?
I tried making the helper class use a common base class but that is not really possible with the template functions.
Also, note that I am limited to C++ 17 for the compiler.
You will need to make sure the public header file (the one with the class that has the pimpl pointer) doesn't expose the header file only class template of the implementation. Use an interface for that like this.
I did not dependency inject the implementation because that should not be needed.
#include <memory>
#include <iostream>
// public header file
// for pimpl pattern I often use an interface
// (also useful for unit testing later)
class PublicItf
{
public:
virtual void do_something() = 0;
virtual ~PublicItf() = default;
protected:
PublicItf() = default;
};
// the public class implements this interface
// and the pimpl pointer points to the same interface
// added advantage you will have compile time checking that
// the impl class will all the methods too.
class PublicClass final :
public PublicItf
{
public:
PublicClass();
virtual ~PublicClass() = default;
void do_something() override;
private:
std::unique_ptr<PublicItf> m_pimpl; // the interface decouples from the template implementation (header file only)
};
// private header file
// this can now be a template
template<typename type_t>
class ImplClass final :
public PublicItf
{
public:
void do_something() override
{
m_value++;
std::cout << m_value << "\n";
}
private:
type_t m_value{};
};
// C++ file for Public class
// inlcude public header and impl header (template)
PublicClass::PublicClass() :
m_pimpl{ std::make_unique<ImplClass<int>>() }
{
};
void PublicClass::do_something()
{
m_pimpl->do_something();
}
// main C++ file
int main()
{
PublicClass obj;
obj.do_something();
return 0;
}
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
I created a class and I want to force anyone who's trying to construct an object, to use unique_ptr. To do that I thought of declaring the constructor protected and use a friend function that returns a unique_ptr. So here's an example of what I want to do:
template <typename T>
class A
{
public:
friend std::unique_ptr<A<T>> CreateA<T>(int myarg);
protected:
A(int myarg) {}
};
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
// Since I declared CreateA as a friend I thought I
// would be able to do that
return std::make_unique<A<T>>(myarg);
}
I did some reading on friend functions and I understood that a friend function provides access to private/protected members of an object of a class.
Is there anyway I can make my example work?
Even without friend functions, my goal is to make the CreateA the only way for someone to create an object.
EDIT
I change the code a bit. I didn't mention that my class takes one template parameter. That makes things more complex apparently.
You can do it this way :-
#include <iostream>
#include <memory>
using namespace std;
class A
{
int arg;
public:
friend unique_ptr<A> CreateA(int myarg);
void showarg() { cout<<arg; }
protected:
A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
return std::unique_ptr<A>(new A(myarg));
}
int main()
{
int x=5;
unique_ptr<A> u = CreateA(x);
u->showarg();
return 0;
}
Output :-
5
If you don't want to use friend function you can make the function static & call it like this :-
unique_ptr<A> u = A::CreateA(x);
EDIT :-
In reply to your edit I rewrote the program & it goes like this :-
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
T arg;
public:
static std::unique_ptr<A> CreateA(T myarg)
{
return std::unique_ptr<A>( new A(myarg) );
}
void showarg()
{
cout<<arg;
}
protected:
A(T myarg): arg(myarg) {}
};
int main()
{
int x=5;
auto u = A<int>::CreateA(x);
u->showarg();
return 0;
}
Simple & easy !!! But remember you cannot instantiate the object of A. Good Luck !!!
The other answers suggest using a static template function, which I agree is the best solution, because it is simpler.
My answer explains why your friend approach didn't work and how to use the friend approach correctly.
There are two problems in your original code. One is that make_unique is not actually a friend of A, so the call make_unique<A<T>>(myarg); does not have access to A's protected constructor. To avoid this , you can use unique_ptr<A<T>>(new A(myarg)) instead. Theoretically it would be possible to declare make_unique a friend but I'm not even sure of the right syntax for that.
The other issue is the template friends problem. Inside a class template, friend <function-declaration> actually declares a non-template friend.
The C++ FAQ suggests two possible workarounds. One of them is to define the friend function inline. However, in that case the function can only be found by argument-dependent lookup. But since the function does not take A<T> (or A<T> &) as argument, it can never be found this way. So this option is not viable to your situation -- it's more suited to operator overloading.
So the only fix is to declare (and optionally define) the template function before the class definition:
#include <memory>
template<typename T>
class A;
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
return std::unique_ptr<A<T>>{new A<T>(myarg)};
}
template <typename T>
class A
{
friend std::unique_ptr<A<T>> CreateA <> (int myarg);
// refers to existing template ^^
protected:
A(int myarg) {}
};
int main()
{
auto x = CreateA<int>(5);
}
Note: It is possible to declare CreateA where I have defined it, and put the function definition later. However, the code I have posted works -- despite A not being defined when new A<T>(myarg) appears in the source -- because CreateA is not instantiated until it is called, at which point A will be defined.
Create a static function that instantiates the protected constructor.
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
std::unique_ptr<A<T>> objB(new A(myarg, t));
objA = std::move(objB);
}
protected:
A(int myarg, T t) {
m_t = t;
}
private:
T m_t;
};
int main() {
int myArg = 0;
std::unique_ptr<A<int>> anotherObjA;
A<int>::CreateA(myArg, anotherObjA, myArg);
return 0;
}
How do I use pimpl for a templated class, when I explicitly instantiate the templates?
All I need is an example code.
What I have tried is:
// MyTemplatedClass.h
template< class T >
class MyTemplatedClass
{
private:
class Impl;
Impl* _pimpl;
public:
void PublicMethod();
}
Here my implementation goes:
// MyTemplatedClass.cpp
template< class T >
class MyTemplatedClass<T>::Impl
{
public:
void PublicMethod();
}
template <class T>
void MyTemplatedClass<T>::Impl::PublicMethod()
{
...
}
Forwarding method call to implementation class:
template< class T >
void MyTemplatedClass<T>::PublicMethod()
{
_pimpl->PublicMethod();
}
Explicit instantiation:
Example with int and double:
template class MyTemplatedClass< int >;
template class MyTemplatedClass< double >;
But it doesn't seem to work.
This would answer your question, but I doubt it does what you hoped to achieve. I suspect you would want to declare the template implementation outside the scope of MyTemplatedClass. It might be a better design to inherit from the template implementation instead of having it as a member variable.
If you compiler does not support extern template declarations I cannot see that having a template pointer to implementation adds any value. You would after all have to have the implementation details you wanted to hide away in the header file anyway.
#include <iostream>
template < class T > class MyTemplatedClass {
private:
template < class U> class Impl {
public:
void ImplPublicMethod() {
std::cout << "Standard implementation" << std::endl;
}
};
Impl<T> * _pimpl;
public:
MyTemplatedClass() : _pimpl(new Impl<T>) { }
~MyTemplatedClass() { delete _pimpl; }
void publicMethod() {
_pimpl->ImplPublicMethod();
}
};
template<> class MyTemplatedClass<int> {
private:
class Impl {
public:
void ImplPublicMethod() {
std::cout << "Integer specialisation" << std::endl;
};
};
Impl * _pimpl;
public:
MyTemplatedClass() : _pimpl(new Impl) { }
~MyTemplatedClass() { delete _pimpl; }
void publicMethod() {
_pimpl->ImplPublicMethod();
}
};
int main(int argc, char ** argv) {
MyTemplatedClass<char> charVersion;
charVersion.publicMethod();
MyTemplatedClass<int> intVersion;
intVersion.publicMethod();
return 0;
}
Methods of a template class always have to be defined in the header. You cannot have a MyTemplatedClass.cpp as compilation unit on its own. What you can do is to #include the file containing the definitions of the methods at the end of MyTemplatedClass.h so that declaration and definition are at least separated at file level. So your problem may be fixed by adding
#include "MyTemplatedClass.cpp"
at the end of MyTemplatedClass.h.
I use pimpls with template classes in my own code, it works for me that way. Your code looks about right - I'd use a std::unique_ptr for pimpl, but I don't see any problems with how you're doing it.
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.