Gmock - strict mock and unique ptr - how to pass mock to impl - c++11

Here is an example code:
class Interface
{
public:
virtual ~Interface(){}
virtual void Start() = 0;
};
class MockInterface: public Interface
{
public:
MOCK_METHOD0(Start, void());
};
class T
{
public:
T(std::unique_ptr<Interface>& impl): impl_(impl){}
private:
std::unique_ptr<Interface>& impl_;
};
I would like to create a strict mock but I'm not sure how to construct it as unique ptr and then pass to T constructor.

#include <gmock/gmock.h>
#include <gtest/gtest.h>
class Interface
{
public:
virtual ~Interface(){};
virtual void Start() = 0;
};
class MockInterface : public Interface
{
public:
MOCK_METHOD0( Start, void() );
};
class T
{
public:
explicit T( std::unique_ptr< Interface > impl ) :
impl_( std::move( impl ) ) {}
void Start()
{
impl_->Start();
}
private:
std::unique_ptr< Interface > impl_;
};
TEST( Interface_test, Interface )
{
auto mock{ std::make_unique< MockInterface >() };
EXPECT_CALL( *mock, Start() );
auto t{ T{ std::move( mock ) } };
t.Start();
}
Posting a complete answer with an example of usage and an update to the class T. It is recommended to move the unique_ptr instead of taking a reference.

Related

static assert on std::is_nothrow_move_constructible_v<class name> is not working

class Base
{
public:
Base(Base&&) = default;
};
class Derived: public Base
{
public:
Derived(Derived&&) = default;
};
int main()
{
static_assert(std::is_nothrow_move_constructible_v<Derived>, "Error noexcept");
}
In this code even if neither Derived nor Base declared move constructor noexcept but still this passes static assert on std::is_nothrow_move_constructible_v<Derived>.
Why?

Passing member function that accepts Base type to class that owns Derived type

Example
In example above I've tried to store pointer-to-member_function of the overloaded function in the template-based class.
The problem is that overloaded function uses Base class as parameter and current class is template class from Derived class.
Handlers
#include <iostream>
#include <string>
class HandlerA
{
public:
void foo(const std::string& m)
{
std::cout << "HandlerA: " << m << '\n';
}
};
class IBaseHandlerB
{
public:
virtual void bar(const std::string& m) = 0;
};
class HandlerB : public IBaseHandlerB
{
public:
virtual void bar(const std::string& m) override
{
std::cout << "HandlerB: " << m << '\n';
}
};
Events
class Event
{
public:
virtual void write(HandlerA&) const = 0;
virtual void write(IBaseHandlerB&) const = 0;
};
class FancyEvent : public Event
{
public:
virtual void write(HandlerA& h) const override
{
h.foo("FancyEvent");
}
virtual void write(IBaseHandlerB& h) const override
{
h.bar("FancyEvent");
}
};
Wrapper and usage example
template <typename T, typename Event>
class HandlerWrapper
{
public:
HandlerWrapper(T&& handler, void(Event::*func)(T&) const)
: m_handlerImpl(std::forward<T>(handler))
, m_eventFn(func) {}
void call(const Event& event)
{
(event.*m_eventFn)(m_handlerImpl);
}
private:
T m_handlerImpl;
void(Event::*m_eventFn)(T&) const;
};
// ------- Usage -------
int main(void)
{
FancyEvent event;
// OK
HandlerWrapper<HandlerA, Event> h(HandlerA(), &Event::write);
h.call(event);
// Error: Candidate constructor not viable: no overload of
// 'writeWithHandler' matching
// 'void (LogEvent::*)(CEFEventHandler &) const' for 2nd argument
HandlerWrapper<HandlerB, Event> h2(HandlerB(), &Event::write);
h2.call(event);
return 0;
}
Question
How to specify correct template type to accept function-to-Base if class template argument is derived from that Base?
My goal is to pass just pointer-to-member_function to another class whenever that class is the same with type that function accepts or derived from it.

Templates: Check and use Methode on compiletime

I know,I know. This question seems to be asked several time. But all the answers are not exactly what I want because they do not resolve the whole thing at compile time. Or they are not working on the actual compiler trio VS,XCode and GCC (without #ifdefs) using C++11 features. Or at least, they lost me during explanation. So I tried on my own:
I tried to implement a method which I can give any type. As long as the type can be converted into a std::string by using std::to_string that should be used. If it is an object of a self-written class, it should have a "toString" method, than the method should use that. It would be fine if this decisions are made during compile time. Here where I come so far:
#include <stdio.h>
#include <iostream>
#include <string>
class Test
{
public:
template <typename T> static auto has_toString_method(T& t) -> decltype(t.toString(), bool()) { return true; }
static int has_toString_method(...) { return 0; }
template< class T> static void toString(T value)
{
toString(value,has_toString_method(value) );
}
template< class T> static void toString(T value,bool)
{
value.toString();
}
template< class T,bool> static void toString(T value,int)
{
printf("It works with to_string");
}
};
class MyToStringTest
{
public:
void toString()
{
printf("It works toString");
}
};
int main ()
{
MyToStringTest tst;
Test::toString(5); // This fails because the compiler tries to resolve the bool arc.
Test::toString(tst);
return 0;
}
Besides that this code is actually not compiling on VS2012 ( I marked the line ), it also is not a full decision on compile time ( I think). What I am missing? What is the fasted, smallest way to get this running?
As addon question. Is it possible, if there are "std::to_string" failing and the "toString" missing to assert or call a "third way"?
UPDATE:
I got the bug, running in circles I was copy and pasting a definition on the wrong place instead of:
template< class T,bool> static void toString(T value,int)
{
I have (of course)to write:
template< class T> static void toString(T value,int)
{
Than It will not only compile, it also will work! But the other questions will remain.
This works:
#include <stdio.h>
#include <cstdint>
#include <iostream>
#include <string>
template<int i>
struct ToStringMethod {
template<typename T>
static void toString(T value) {
printf("It works with 3rd method\n");
}
};
template<>
struct ToStringMethod<1> {
template<typename T>
static void toString(T value)
{
value.toString();
}
};
template<>
struct ToStringMethod<2> {
template<typename T>
static void toString(T value)
{
printf("It works with to_string\n");
}
};
class Test
{
public:
template <typename T> static auto has_string_support(T& t) -> decltype(t.toString(), std::int8_t()) { return true; }
template <typename T> static auto has_string_support(T& t) -> decltype(std::to_string(t), std::int16_t()) { return true; }
static std::uint32_t has_string_support(...) { return true; }
template< class T> static void toString(T value)
{
ToStringMethod<sizeof(has_string_support(value))>::toString(value);
}
};
class MyToStringTest
{
public:
void toString()
{
printf("It works toString\n");
}
};
class NoneString {};
int main ()
{
MyToStringTest tst;
NoneString none;
Test::toString(5); // This fails because the compiler tries to resolve the bool arc.
Test::toString(tst);
Test::toString(none);
return 0;
}
Following may help:
#include <string>
#include <type_traits>
#define HAS_MEM_FUNC(name, Prototype, func) \
template<typename U> \
struct name { \
typedef char yes[1]; \
typedef struct { char dummy[2]; } no; \
template <typename T, T> struct type_check; \
template <typename T = U> \
static yes &chk(type_check<Prototype, &T::func> *); \
template <typename > static no &chk(...); \
static bool const value = sizeof(chk<U>(0)) == sizeof(yes); \
}
HAS_MEM_FUNC(has_to_string, std::string(T::*)() const, toString);
class Test
{
public:
template<typename T>
static typename std::enable_if<has_to_string<T>::value, std::string>::type
toString(const T& t) {
/* something when T has toString ... */
return t.toString();
}
template<typename T>
static typename std::enable_if<!has_to_string<T>::value, std::string>::type
toString(const T& t) {
/* something when T doesnt have toString ... */
return std::to_string(t);
}
};
class MyToStringTest
{
public:
std::string toString() const
{
return "It works toString";
}
};
int main(int argc, char** argv)
{
MyToStringTest tst;
Test::toString(5);
Test::toString(tst);
return 0;
}

Calling a managed class function from an unmanaged class object

This is a class library clr/c++ project.
Class A is unmanaged c++, class B managed c++.
I would like to create an object of B from a C# application and call the "void Sign" with that object and catch the StatusEvent in C#.
How to call B::Showsts from A::call_A in order to achieve this? Please keep in mind that call_A is called from a delegate of the B class object.
Thank you in advance!
public class A{
public:
int call_A();
};
public ref class B{
private:
A* a1;
public:
void Sign(String^ ufile);
void Showsts(string sts);
delegate void GetResult(String^);
event GetResult^ StatusEvent;
SpyrusLib(void){
a1=new A();
}
protected: ~SpyrusLib(){
delete a1;
}
private:
String^ str;
delegate int MySignDelegate(String^);
int MySign(String^ file);
void Callbacksign(IAsyncResult ^ar);
};
void B::Sign(String^ ufile){
MySignDelegate^ signDel = gcnew MySignDelegate( this, &B::MySign );
AsyncCallback^ cb = gcnew AsyncCallback( this, &B::Callbacksign);
signDel->BeginInvoke( ufile , cb, signDel );
}
int B::MySign(String^ file){
stdstr=msclr::interop::marshal_as<std::string>(file);
a1->call_A(stdstr);
}
void B::Showsts(string sts){
str = gcnew String(sts.c_str());
StatusEvent(str);
}
int A::call_A(string stat){
?-Showsts(stat);
}
I'm not sure it's the best solution but I solved it adding the following things to the classes:
typedef void (__stdcall * Unmanagedstatus)(string sts);
using namespace std;
public class A{
private:
Unmanagedstatus sendmsg;
public:
int call_A();
spyrus(Unmanagedstatus unm)
{
sendmsg=unm;
}
};
public ref class B
{
private:
delegate void Managedstatus(string);
Managedstatus^ managed;
IntPtr unmanaged;
A* a1;
public:
SpyrusLib(void)
{
managed = gcnew Managedstatus(this, &B::Showsts);
unmanaged = Marshal::GetFunctionPointerForDelegate(managed);
a1=new A((Unmanagedstatus)(void*)unmanaged);
}
}
int A::call_A(string stat){
sendmsg(stat); // this will call B::Showsts and the events raised
//from Showsts are also working in the C# app
}

Runtime polymorphism in C++

I have an interface, and I was trying an example on dynamic polymorphism as follows:
#include <iostream>
using namespace std;
class foo{
public:
virtual void set();
virtual void printValue();
};
class fooInt : public foo{
private:
int i;
public:
int get(){
return i;
}
void set(int val){ //override the set
i = val;
}
void printValue(){
cout << i << endl;
}
};
int main(){
foo *dt; //Create a base class pointer
dt = new fooInt; //Assign a sub class reference
dt->set(9);
}
However when I compile this, I get no matching function for call to ‘foo::set(int)’. Where am I going wrong? I tried to read this article, and I still couldn't figure out the mistake.
class foo has no method set(int). It has a method set(), but no method set(int).
If you intend to override an inherited method, the superclass method and your method must have the same signature:
class foo {
...
// If you really want an abstract class, the `= 0`
// ensures no instances can be created (makes it "pure virtual")
virtual void set(int) = 0;
...
}
This is because your definition of
virtual void set();
Should be
virtual void set(int val);
The corrected program is given here
#include <iostream>
using namespace std;
class foo {
public:
virtual void set(int val)=0;////////here you have void set() function with no argument but you tried to override void set(int val) which take one argument.
virtual void printValue()=0;
};
class fooInt : public foo{
private:
int i;
public:
fooInt()
{
cout<<"constructor called\n";
}
int get(){
return i;
}
void set(int val){ //override the set
i = val;
}
void printValue(){
cout << i << endl;
}
};
int main(){
foo *dt; //Create a base class pointer
dt=new fooInt;
dt->set(9);
dt->printValue();
}
Fault of the previous program were
1.You tried to override set() {no argument} with set(int val){one argument}.
2.When a class contain a pure virtual function,it must be implemented by its derived classes.
3. No object can be created of a class which contain a pure virtual function.But ref can be created.
Thanks

Resources