working on implementing an Serial receive library for a specific hardware sending information to a ESP8266 device, I came across the following issue
for some background:
I use sloeber the eclipse IDE for arduino programming, with Arduino IDE the same issue exists
__cplusplus gives me 201103, so I assume I am on c++11
explanation of the setup:
I have derived classes which represents interpreted packages received from serial
these classes are all derived form on base class which implements some common methods, here methodA (in reality: length of
data, and getter for the data)
to forward these packets around I have created a class which has a member of a struct (sData) which has a tagged union inside. for simplicity I only use sData here not the class containing it.
the union uUnion is the one holding the packets content in form of derived packages, only one at a time, but able to contain every derived class available.
i do not use any dynamic object creation (no new), to prevent memory leaks
maybe there are better solution to this problem. Ideas are appreciated. But I would like to focus on why my implementation is not working
problem
the usage of the members-functions of the derived classes out of the union.
I can call them directly without problem.
But I am not able to create a pointer out of the union to the derived class instance and call that member.
//this is the base class
class cBaseA{
public:
virtual void methodA(void){
Serial.print(" A ");
Serial.println(i);
}
int i; //some attribute to work with
private:
};
//first derived class
class cDerivedA: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedA ");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii; //additional attribute
private:
};
//second derived class
class cDerivedB: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedB ");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii;
private:
};
//third derived class
class cDerivedC: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedC");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii;
private:
};
//this is the structure to pass different derived instances around
struct sData{
enum eDataType{
eunkown,
eDerivedA,
eDerivedB,
eDerivedC
} DataType;
union uUnion{
cDerivedA DerivedA;
cDerivedB DerivedB;
cDerivedC DerivedC;
~uUnion(){};
uUnion(){};
} ;
uUnion DataUnion;
sData(void){DataType=eDataType::eunkown;};
sData(const sData &Data){
this->DataType=Data.DataType;
switch(this->DataType){
case eDataType::eDerivedA:
this->DataUnion.DerivedA=Data.DataUnion.DerivedA;break;
case eDataType::eDerivedB:
this->DataUnion.DerivedB=Data.DataUnion.DerivedB;break;
case eDataType::eDerivedC:
this->DataUnion.DerivedC=Data.DataUnion.DerivedC;break;
case eDataType::eunkown:
break;
}
}
~sData(){};
};
void DataFunction(struct sData *Data){
Serial.println("A1:");
Data->DataUnion.DerivedB.methodA(); //works fine
cDerivedB *DerivedB;
DerivedB=&(Data->DataUnion.DerivedB); //this works
DerivedB->methodA(); //compiles, but execution exception, code 28
}
void setup(){
Serial.begin(9600);
delay(2000);
sData Data;
cDerivedB DerivedB1;
DerivedB1.i=1;
DerivedB1.ii=2;
Data.DataType=sData::eDataType::eDerivedB;
Data.DataUnion.DerivedB=DerivedB1;
DataFunction(&Data);
}
what I tried so far:
the absence of the virtual destructor of cBaseA has no influence (I tried already with it)
to make the union anonymous did not changed anything
to make a reference to the unions content results in the same error:
cDerivedB &DerivedB;
DerivedB=&(Data->DataUnion.DerivedB);
DerivedB.methodA();
I am able to make copy to out of the union to the base class, but this causes slicing, and the call ends in the base class, not as I need in the derived class
the question is: why does this exception happen, if the direct call is possible?
What is the right way to get a handle (pointer, reference) of the unions content and call the member? I know that there are discussions out there, that unions should only contain simple data types. Is this just a flaw of the compiler (c+11) letting me write this?
But still, direct access is possible. Why not via pointer?
many thanks in advance if somebody is able to put that cloud away I can not see through.
Related
How to achieve gtest or gmock for the private and protected member function. I am new to gtest and gmock. Below is the code for which i need to do gtest or gmock along with my attemp.
constexpr static char _session[]{"S_ID"};
typedef struct {
int session;
} Session;
typedef std::function<void(const Session &)> SessionCallback_t;
class Service : public ParentService {
public:
Service();
void registerCallback(const SessionCallback_t & callback);
protected:
virtual void notifyHandler(const Json::Value & data) override;
virtual void notifyState();
private:
Session mSession;
SessionCallback_t mCallback;
void jsonParse(const Json::Value & json_data);
};
My Attemp which doesn't compile
class TestService : public Service {
public:
TestService(): Service() {
}
bool registerCallback(const SessionCallback_t & cb) {
// how to achive this?
}
};
class MyTestService : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
}
};
TEST_F(MyTestService , registerCallbackTest) {
TestService service;
EXPECT_TRUE(service.registerCallback(SessionCallback_t));
}
I am stuck with the below interface
1.registerCallback()
2.notifyHandler()
3.notifyState()
4.jsonParse()
Please though some light to proceed further.
Welcome to Stack Overflow!
First, let me recommend this recent episode of CppCast on Designing for Testing. The podcast notes that if you find your code is hard to test, it means it is too tightly coupled and is thus poorly designed.
It also (rightly, IMHO) recommends that you test only public functions. If you find yourself needing to test the private functions, you should probably refactor the code.
One way to do that is to break your code into multiple classes with the public functions you want to test. Then, your composite class can either create and own the class directly (appropriate if it's a basic type with no dependencies or complex resources of its own such as a vector or string class) or can use dependency injection to pass in the dependencies as constructor or method parameters (appropriate for databases, network connections, file systems, etc.).
Then in testing, you pass in a test double, such as a mocked object or a simplified implementation like an in-memory database instead of an out-of-process database connection, that acts like the object but does what you need in the test situation.
That's the basic advice. In your specific case, it looks like you're trying to override a non-virtual function in your TestService. What are you wanting to test exactly?
I wouldn't expect EXPECT_TRUE(service.registerCallback(SessionCallback_t)); to compile because SessionCallback_t names a type, not an instance of a type, so you can't pass it in. Again, what are you trying to accomplish?
Update to comment:
Mocking requires virtual functions (or duck typing) and dependency injection.
If you just want to test registerCallback(), I suspect you don't need a mock at all. Rather, you need to look at the function's documentation to see what it says it will do -- sometimes called the contract. For instance, what are the preconditions and postconditions of the function? What are the error cases it might encounter? These are what a unit test should cover.
For instance, does it retain only one callback (hint: as written, yes)? What happens when you call it when there is already a callback registered? Does it tolerate default-initialized std::function objects being passed in?
The bigger question is, how do you validate that your test is correct. If you start triggering notifications on your callback, you're venturing beyond the scope of testing this function in isolation. Instead, you could create an accessor class in your test to publicize what is private so you can validate. Still, you can't compare std::function for equality, so the best you can do is to invoke it and check that an expected side effect happens:
class TestService : public Service {
public:
const SessionCallback_t& getCallback() const { return mCallback; }
};
struct TestCallback
{
int mCount = 0;
void operator()( const Session& ) { ++mCount; }
};
Then in your test, you can write a tests like:
TEST_F(MyTestService , Test_registerCallback_BadCallback) {
auto service = TestService{};
EXPECT_THROW( service.registerCallback( SessionCallback_t{} ), std::out_of_range );
}
// Register and check that it's our callback
TEST_F(MyTestService , Test_registerCallback_CallbackSaved) {
auto service = TestService{};
auto callback = TestCallback{};
EXPECT_TRUE( service.registerCallback( callback ) );
EXPECT_EQ( callback.mCount, 0 );
auto actualCallback = service.getCallback();
EXPECT_TRUE( actualCallback );
actualCallback();
EXPECT_EQ( callback.mCount, 1 );
}
TEST_F(MyTestService , Test_registerCallback_CallbackOverwrite) {
auto service = TestService{};
auto callback1 = TestCallback{};
auto callback2 = TestCallback{};
EXPECT_TRUE( service.registerCallback( callback1 ) );
EXPECT_TRUE( service.registerCallback( callback2 ) );
EXPECT_EQ( callback1.mCount, 0 );
EXPECT_EQ( callback2.mCount, 0 );
auto actualCallback = service.getCallback();
EXPECT_TRUE( actualCallback );
actualCallback();
EXPECT_EQ( callback1.mCount, 0 );
EXPECT_EQ( callback2.mCount, 1 );
}
I`m trying to implement something like this using C++11.
class Proto{
public:
virtual void fu() = 0;
};
class Impl: public Proto{
public:
void fu();
};
void Impl::fu(){
LOG_INFO("im fu");
}
class Inv{
public:
void useFu(void (Proto::*)());
};
void Inv::useFu(void (Proto::*fu)()){
//fu();
};
void main(){
Impl impl;
Inv inv;
//inv.useFu(impl.fu);
}
useFu(void (Proto::*)()) must be declared in this way because, fu() uses some specific to Proto functionality's
I have two places were things going wrong.
First is fu() call itself and second how to pass fu as parameter inv.useFu(impl.fu).
Edit after bipll answer
The suggested usage of inv.useFu() solves the second problem of my question.
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I still need to call fu as a pointer to member function;
The way your useFu is declared now, it should be called as
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I guess that's not what you wanted. It should rather be
template<class F> void useFu(F &&f) { std::invoke(std::forward<F>(f)); }
or simply
void useFu(std::function<void()> f) { std::invoke(std::move(f)); }
and called as
useFu([&]{ impl.fu(); });
(Rather than using a lambda you can bind the method to the object with std::bind in the latter call but almost nobody ever does that.)
I searched many pages, and I think I have known how to write the std::hash. But I don't know where to put it.
An example is presented here http://en.cppreference.com/w/cpp/utility/hash .
However, I defined my type Instance in namespace ca in file instance_management.h. I want to use unordered_set<Instance> in the same file in another class InstanceManager. So I write the following code:
namespace std
{
template <> struct hash<ca::Instance>
{
size_t operator()(const ca::Instance & instance) const
{
std::size_t seed = 0;
// Some hash value calculation here.
return seed;
}
};
} // namespace std
But where should I put it? I tried many locations but all failed.
I am using visual studio 2013. I tried to put the previous code in some locations but all failed to compile it.
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
There are several ways.
Specializing std::hash
In your code make sure that your std::hash<Instance> specialization is preceded immediately by the Instance class definition, and followed by the use of the unordered_set container that uses it.
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
One drawback is that you can have funny name lookup interference when passing a std::hash<ca::Instance> to other functions. The reason is that the associated namespace (ca) of all the template arguments of std::hash can be used during name lookup (ADL). Such errors are a bit rare, but if they occur they can be hard to debug.
See this Q&A for more details.
Passing your hash to unordered_set
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
Here, you simply pass your own hash function to the container and be done with it. The drawback is that you have to explicitly type your own container.
Using hash_append
Note, however, there is the N3980 Standard proposal is currently pending for review. This proposal features a much superior design that uses a universal hash function that takes an arbitrary byte stream to be hashed by its template parameter (the actual hashing algorithm)
template <class HashAlgorithm>
struct uhash
{
using result_type = typename HashAlgorithm::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
HashAlgorithm h;
using std::hash_append;
hash_append(h, t);
return static_cast<result_type>(h);
}
};
A user-defined class X then has to provide the proper hash_append through which it presents itself as a byte stream, ready to be hashed by the univeral hasher.
class X
{
std::tuple<short, unsigned char, unsigned char> date_;
std::vector<std::pair<int, int>> data_;
public:
// ...
friend bool operator==(X const& x, X const& y)
{
return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
}
// Hook into the system like this
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
using std::hash_append;
hash_append(h, x.date_);
hash_append(h, x.data_);
}
}
For more details, see the presentation by the author #HowardHinnant at CppCon14 (slides, video). Full source code by both the author and Bloomberg is available.
Do not specialise std::hash, instead write your own hash function object (see Edge_Hash below) and declare your unordered_set with two template arguments.
#include <unordered_set>
#include <functional>
namespace foo
{
// an edge is a link between two nodes
struct Edge
{
size_t src, dst;
};
// this is an example of symmetric hash (suitable for undirected graphs)
struct Edge_Hash
{
inline size_t operator() ( const Edge& e ) const
{
static std::hash<size_t> H;
return H(e.src) ^ H(e.dst);
}
};
// this keeps all edges in a set based on their hash value
struct Edge_Set
{
// I think this is what you're trying to do?
std::unordered_set<Edge,Edge_Hash> edges;
};
}
int main()
{
foo::Edge_Set e;
}
Related posts are, eg:
Inserting in unordered_set using custom hash function
Trouble creating custom hash function unordered_map
Thanks to everyone.
I have found the reason and solved the problem somehow: visual studio accepted the InstanceHash when I was defining instances_. Since I was changing the use of set to unordered_set, I forgot to specify InstanceHash when I tried to get the const_iterator, so this time the compiler tried to use the std::hash<> things and failed. But the compiler didn't locate the line using const_iterator, so I mistakenly thought it didn't accept InstanceHash when I was defining instances_.
I also tried to specialize the std::hash<> for class Instance. However, this specialization requires at least the declaration of class ca::Instance and some of its member functions to calculate the hash value. After this specialization, the definition of class ca::InstanceManage will use it.
I now generally put declarations and implementations of almost every classes and member functions together. So, the thing I need to do is probably to split the ca namespace scope to 2 parts and put the std{ template <> struct hash<ca::Instance>{...}} in the middle.
I have a COM interface exposed from my application which is used by the third party plugins. Now, I need to add a new method to this interface but can not change the GUID of the interface as it will break all the existing plugins. I was told that if I add the new methods at the end of the interface it will work without issues as finally COM interface is a table of function pointers. These new methods will only be used by newly written plugins. I read this post and the first comment in Raymond Chen's blog: http://blogs.msdn.com/b/oldnewthing/archive/2005/11/01/487658.aspx but the situation mentioned in comment won't happen in my case as it is Windows only application. I know theoretically I should change the interface GUID. What would be the correct solution in this case? or will this approach work?
You can usually get away with adding new methods to the end of an existing interface without breaking compatibility. But as you have been reading, there are subtle cases where this can break. Especially when multiple inheritance is already being used.
The correct solution is to simply declare a new interface for the new methods. Leave your existing interfaces alone. Then have your existing objects implement both interfaces or use inheritance to have the new interface inherit from the old.
For example, if this is our original code. (I'll pretend this is done without IDL files for brevity).
Original code:
class IPublicInterface : public IUnknown
{
public:
virtual void M1() = 0;
virtual void M2() = 0;
}
class MyPublicClass : IPublicInterface
{
public:
// IPublicInterface
void M1();
void M2();
// IUnknown
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
Now let's say we want to add a new method to this object called M3 without breaking users of the existing interface and object. The correct solution would be to add a new interface. For convenience, it can just inherit from the original interface.
class IPublicInterface2 : public IPublicInterface
{
public:
virtual void M3() = 0;
};
Now modify the class to inherit from both this new derived interface:
class MyPublicClass : public IPublicInterface2
{
public:
// IPublicInterface
void M1();
void M2();
// IPublicInterface2
void M3();
// IUnknown
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
Update QueryInterface to support both calls for both the original UUID of IPublicInterface as well as IPublicInterface2.
HRESULT MyPublicClass::QueryInterface(GUID& iid, void** ppv)
{
// QI request for original interface
if ((iid == uuidof(IPublicInterface) || (iid == uuidof(IUnknown))
{
*ppv = (IPublicInterface*)this;
AddRef();
return S_OK;
}
else if (iid == uuidof(IPublicInterface2)
{
*ppv = (IPublicInterface2*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
Alternatively, IPublicInterface2 does not need to inherit from the original IPublicInterface. In that case, the implementing class inherits from both interfaces. In the QueryInterface implementation, you will need to be consistent about how you handle a possible ambiguous cast to IUnknown.
I am writing an GL effect system in my application so i have a superclass called
cEffect - which handles loading/parsing configuration file for each effect
and other inherited classess
cFX<name> - for every effect i add ( blur, bloom, chaos,... ).
The code is simplified here but looks like this:
Class cEffect
{
public:
bool ParseString(...);
private:
int m_nStartFrame;
int m_nEndFrame;
float m_fSpeed;
};
// Blur effect
Class cFXBlur : public cEffect
{
public:
bool RenderFrame(...);
};
// Bloom effect
Class cFXBloom : public cEffect
{
public:
bool RenderFrame(...);
};
// Scene drawing effect
Class cFXScene : public cEffect
{
public:
bool RenderFrame(...);
};
// Clear the depth/color buffer
Class cFXClearBuffers : public cEffect
{
public
bool RenderFrame(...);
}
Now, the demo engine handles a
std::vector<cEffect *> m_pvEffects;
Vector that has a list of effects added.
And when an effect is added to the current time (let's say i add a blur)
i add it like:
// Blur to be added
cEffect *newEffect = new cFXBlur;
newEffect->SetStartTime(x);
newEffect->SetEndTime(y);
newEffect->SetPower(13.0f);
newEffect->SetTexture(...);
// Now add the effect to the effects list.
m_pvEffects.push_back(newEffect);
Now, when i render i iterate through m_pvEffects list - but also i would like to call
an RenderFrame method ( which is public in every CFX<name> effect).
(*it)->RenderFrame(...)
But compiler says:
error C2039: 'RenderFrame' : is not a member of 'CEffect'
I kinda understand why it happens but can't really think of a way how can i fix this,
can you guys help me out please - it seems like i lost the plot ...
Thanks for any suggestion, what can i do to add CFX to a cEffect vector and later
use -> RenderFrame method?
You should change your class cEffect to:
Class cEffect
{
public:
bool ParseString(...);
virtual bool RenderFrame(...) = 0;
private:
int m_nStartFrame;
int m_nEndFrame;
float m_fSpeed;
};
You need the keyword virtual, if you want to redefine a method in a subclass. The = 0 makes the class cEffect abstract (i.e. you cannot create an object directly of the type cEffect), therefore subclasses must implement the method RenderFrame(...)
The error occurs, because cEffect has no member function called RenderFrame. What you want is a virtual function, a fundamental concept of object oriented programming. Basically you need to add a function
virtual bool RenderFrame(...);
to your cEffect definition. The virtual keyword basically tells the compiler to resolve it at runtime. This means if you call this method on a cEffect pointer or a reference, the corresponding method of the concrete derived class this pointer or reference point to is called. In this case you should also declare the method as virtual in all derived classes (although this is not neccessary, it makes your code clearer).
If you do not want the base class method to do anything and you want to require all derived classes to override it with their own implementation, then you can make this method pure virtual in the base class, by decralring it like
virtual bool RenderFrame(...) = 0;
This basically tells the compiler, that this is an abstract method, which doesn't have a concrete implementation and is only implemented by derived classes.
This is a very simplified explanation (appologies to every expert who thinks my wordings not 100% exact). You should read some more material on object oriented programming, especially in conjunction with C++.