#include <queue>
struct model_shell_t
{
model_shell_t() {clear();}
void clear();
void Release() {clear(); model_pool._delete(this);}
void SetArgument(byte4 _type, byte4 _arg1, byte4 _arg2)
{
switch( _type )
{
case 100:
if( tail_enable && !_arg1 )
{
tail_deque.clear();//tail_queue.c.clear(); // Error C2248 Cannot access protected member of queue
}
tail_enable = _arg1;
break;
case 101:
tail_interval = _arg1;
tail_count = _arg2;
break;
}
}
queue<model_t> tail_queue;
byte4 tail_enable;
byte4 tail_interval;
byte4 tail_count;
deque<model_t> tail_deque;
};
Another :
for( byte4 i = 0; i < ms->tail_queue.size(); i++ )
{
//ms->tail_queue.c[i].bind_model = &bind_ms->tail_queue.c[i];
ms->tail_deque[i].bind_model = &bind_ms->tail_deque[i];
}
error C2248: 'std::queue<_Ty>::c' : cannot access protected member
declared in class 'std::queue<_Ty>'
When i upgrade solution from VS2003 to VS2008 i cant use clear() function.
How can i use it ?
Thank you
EDITED : With help from Igor Tandetnik i have change above
VS2003 was wrong, VS2008 is right. The underlying container should be a protected member, and shouldn't be accessible. Your code relies on a non-conforming implementation detail - essentially, on a compiler bug that has since been fixed.
As you apparently need direct access to elements, you are breaking queue abstraction anyway. It'd be easiest to just use std::deque directly, without a wrapper.
If for some reason you insist on using std::queue, another approach would be for model_shell_t to privately derive from it, rather than having it as a member. This way it'll have direct access to c. Though it's unclear why you would want to take such a circuitous route to getting a std::deque member.
Related
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.
How can I know that for a particular ComboBox which Dialog Style is being used? Is there any Win32 API which can give me that information?
I am using CDialog for a few ComboBox, CDialogEx for some, and an in-house Dialog class, let's say Ctl3dDialogEx, for others. GetClassName() will return the Class name of the ComboBox (if I am passing a ComboBox Handler) which can be "CComboBox".
Is there any Win32 API where I will pass the ComboBox Handler and it will return back to me the Dialog class name, for eg : "CDialog", "CDialogEx", "Ctl3dDialogEx", etc?
Below code will help to understand maybe:
void ComboBox_DoSomeManipulation( HWND hldg , int n )
{
/*"hldg" is the handler of the Current ComBobox */
LPTSTR lpClassName;
int nMaxCount = 256;
/*This will return "CComboBox" as value in lpClassName */
GetClassName(hldg , lpClassName , _count_of(nMaxCount));
/*Is there any WIN API like above which can give */
/* Dialog class information like CDialog, CDialogEx */
/* which the ComboBox is using ? */
}
If your combo-box can somehow get hold of a genuine pointer to its parent window, then you can use dynamic_cast<CDialogEx*>(pParent) to see if it's CDialogEx (returns nullptr if not). You will need several separate checks, starting from the most derived class! So, if your Ctl3dDialogEx is derived from CDialogEx, then:
. . .
CWnd *pParent = pCombo->GetParent(); // This, as is, is not valid code!
if (dynamic_cast<Ctl3dDialogEx*>(pParent) != nullptr) {
// It's a Ctl3dDialogEx parent
}
else if (dynamic_cast<CDialogEx*>(pParent) != nullptr) {
// It's a CDialogEx
}
else { // Assuming no other options …
// It's a CDialog
}
I would recommend making an accessible (static?) copy of the parent window's this pointer during initialisation, if you can. But there are other ways …
For example, assuming you have control over the definition of ComboBox_DoSomeManipulation and when it's called, change the first argument from an HWND to a CWnd* and, when you call it, use this rather than this->m_hwnd. (But this depends on the structure of your code!)
There is no Windows API help since all those dialogs will be subclassing the Windows DIALOG class. If this is all in process, and you are using the same MFC instance, you might be able to do this:
CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);
if (pWnd != NULL)
{
if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialog))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogEx))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogxyz))
{
}
}
Back in the old days, MS compilers used with MFC didn't play well with dynamic_cast<>, so generally, when using MFC, I don't use it. I probably should have more trust in it, but I was stuck using Visual C++ 6 until 2008, so I am probably a little jaded. The more "standard" "MFC way" is to use the MFC macros...
Another possible ways is something like:
if (CDialogxyz* pDlgxyz = DYNAMIC_DOWNCAST(CDialogxyz, pWnd))
{
}
else if (CDialogEx* pDlgEx = DYNAMIC_DOWNCAST(CDialogEx, pWnd))
{
}
else if (CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, pWnd))
{
}
ZeroCopy messaging is something that can be implemented in zeromq, but is it possible to use it with the zmqpp c++ bindings? There is almost no documentation, and I was not able to find anything in the examples...
I would switch to cppzmq.
It's a more active project and maintained by some of the core libzmq people.
It's header only and has support for zero copy.
Just simply use zmqpp::message::copy().
In the zmqpp source code we can see:
void message::copy(message const& source)
{
_parts.resize( source._parts.size() );
for(size_t i = 0; i < source._parts.size(); ++i)
{
_parts[i] = source._parts[i].copy();
}
// we don't need a copy of the releasers as we did data copies of the internal data,
//_releasers = source._releasers;
//_strings = source._strings
}
the _parts which defined as:
private:
typedef std::vector<frame> parts_type;
parts_type _parts;
so, source._parts[i].copy() actually call zmqpp::frame::copy() which defined here:
frame frame::copy() const
{
frame other( size() );
other._sent = _sent;
if( 0 != zmq_msg_copy( &other._msg, const_cast<zmq_msg_t*>(&_msg) ) )
{
throw zmq_internal_exception();
}
return other;
}
zmqpp::frame::_msg in the code snippet is defined as zmq_msg_t. All zmq_msg_t object in the frame objects of source zmqpp::message object been zero copied by zmq_msg_copy to new zmqpp::message object.
so, zmqpp::message::copy() help us get a new zmqpp::message object which it's all frame is zero copied from the source zmqpp::message object.
Sooo...
I have written a plugin, and the whole plugin works fine.
ONLY PROBLEM:
My TS3 Client crashes.
To give a context:
(Warning: That code is just poorly pasted. On GitHub, it crashes at line 270 and 285)
// Helper Function
String^ getChannelName(uint64 serverConnectionHandlerID, uint64 channelID) {
char* tmp;
if (ts3Functions.getChannelVariableAsString(serverConnectionHandlerID, channelID, CHANNEL_NAME, &tmp) == ERROR_ok) {
return marshal_as<String^>(tmp);
}
else
{
return "ERROR_GETTING_CHANNELNAME";
}
}
void assemble_a() {
List<String^>^ clients;
List<String^>^ channel;
// Some middlepart here, but I made sure it works as it should
// And the actual part where it is crashing
if (resChL == ERROR_ok) {
for (int i = 0; channelListPtr[i]; ++i) {
String^ a = getChannelName(schid, channelListPtr[i]);
const char* b = (const char*)(Marshal::StringToHGlobalAnsi(a)).ToPointer();
ts3Functions.logMessage(b, LogLevel_DEBUG, "DEBUG_VC", schid);
if (String::IsNullOrEmpty(a) == false) {
channel->Add(a); // It crashes RIGHT at this point
}
}
}
}
So I am asking on the TS3 forum for a long time, got a lot of answers, and noone could tell me why it actually crashes, and I didn't manage to figure it out on my own either.
It does actually print the channel name [*spacer0]t but as soon as it should append it to the String List, it crashes.
It throws the message The thread has tried to write or read from a virtual address that it does not have the accesspermissions for.
I seriously have no idea what to do, trying to fix it now for over 2 weeks.
For full context: GitHub Sourcecode
Sorry if this question MIGHT be a little out of topic here (Is it? I don't know...) but I don't really know what to do with that problem anymore...
EDIT:
Errormessage from try/catch is:
System.NullReferebceException: The Objectreference was not set to the Objectinstance, occured in tsapi.assembleGrammar()
List<String^>^ channel;
...
channel->Add(a);
channel is null. You need to initialize it with something, probably gcnew List<String^>(). I'm not sure why you're getting an access denied message instead of NullReferenceException.
Other issues
Make sure you're handling all the unmanaged strings properly. For example, does getChannelVariableAsString require a call to explicitly free the buffer? Be absolutely sure to call FreeHGlobal to free the memory that StringToHGlobalAnsi allocated for you.
I am working on a COM-style complier cross-compatible plugin framework relying on compatible virtual table implementations for ABI compatibility.
I define interfaces containing only pure virtual member functions and an overridden delete operator to channel destruction to the place of implementation.
This works well with extern "C" factory functions instantiating the plugin implementation of the interface and returning an interface-type pointer.
However, I was wondering if smart pointers wouldn't be a more modern way to manage the lifetime of the plugin object. I think I have actually managed to
create a standard-layout shared_ptr/weak_ptr that uses a reference count object defined and implemented the same way as the plugin interfaces.
It looks something like this:
class IRefCount
{
public:
virtual void incRef() = 0;
virtual void decRef() = 0;
virtual bool incRefIfNZ() = 0;
virtual void incWRef() = 0;
virtual void decWRef() = 0;
virtual long uses() const = 0;
protected:
~ref_count_base() = default; //prohibit automatic storage
}
template <typename Ty>
class shared_ptr
{
private:
Ty* ptr_;
IRefCount* ref_count_;
public:
//member functions as defined by C++11 spec
}
Three questions:
Before the smart pointer the factory function looked like this:
extern "C" IPlugin* factory() { try { return new Plugin(); } catch (...) { return nullptr; } }
Now, it looks like this:
extern "C" shared_ptr<IPlugin> factory() { try { return shared_ptr<IPlugin>(new Plugin()); } catch (...) { return nullptr; } }
VS2013 is giving me warning C4190: 'factory' has C-linkage specified, but returns UDT 'shared_ptr' which is incompatible with C. According to MSDN this is OK, provided that both caller and callee are C++.
Are there any other potential issues with returning standard-layout objects from "C" linkage functions?
Calling conventions. Should I be specifying __stdcall for all pure-virtual interface functions and factory functions?
I am using <atomic> for the reference count. I am writing platform-independent code and I have not yet tried compiling for ARM. According to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html armcc does not implement std::atomic. Any better compilers/stl out there?