Overloading () operator inside structure in cpp - c++

I came across the following code in a project.
map_erase_if(cfgIp.m_raw, RawCreate());
I understand that this will call the function defined by () inside the structure.
The Rawcreate is a structure which is given below .
struct RawCreate {
bool operator()(const Device::StoreElm& el) {
Pcap* pcap = NULL;
pcap = Pcap::findServer(el.second->name());
if (!pcap) {
try {
MEM_NEW(pcap,Pcap(*el.second));
} catch (Exception& ex) {
MAND_LOG(DBG_SIPTCP, "Error:%s", ex.what());
}
}
for (RejItr itr = CfgIp::m_rejectList.begin(); itr != CfgIp::m_rejectList.end(); ++itr) {
if(ip_equal(itr->first, pcap->getInterface(), false) && !itr->second.empty()) {
pcap->blockReg();
}
}
if (pcap) {
MEM_DELETE(el.second);
return true;
}
return false;
}
};
I have seen operator overloading with class objects.I know class and structure has only few differences in cpp.But using overloading within a structure in this way is a new thing for me.Can any one clarify its usage?

RawCreate()
I understand that this will call the function defined by () inside the structure.
If RawCreate is a function, then this will call it. If it is a type, then it will construct an instance. RawCreate is a class, so the latter is true. T::operator() is not called by this expression.. unless RawCreate is a variable of type T that defines the operator.
I know class and structure has only few differences in cpp
Just to clarify, the only difference is that classes declared with the struct keyword and those declared with class keyword have a different access specifier by default.
Can any one clarify its usage?
The documentation of map_erase_if should describe how the operator is used. Presumably, the operator() of the functor is used as a predicate for erase.

RawCreate() creates an instance of RawCreate.
Your code works like this code:
RawCreate c;
map_erase_if(cfgIp.m_raw, c);
but avoids creating an unnecessary variable.
Presumably, map_erase_if is then going to call the instance's operator() with each member of cfgIp.m_raw (or pass the instance on to something that does).

As the others said, RawCreate() does not call the operator (), it just creates an instance (which is then copied over).
The operator () is then (most likely) called for each item of the map when iterating during map_erase_if() (and if the operator returns true, the item will be erased, if the function works as the name advertises).

Related

Unable to call member function pointer that is inside a struct

I've been racking my brain over getting the syntax right on declaring, defining and finally calling a member function pointer inside my program.
I'm writing a window manager with Xlib, and am trying to enable the user to define all key bindings in a vector of Keybinds. The Keybind struct contains more member variables, which I have left out here for the sake of brevity.
Here's what I've got so far.
Keybind, a struct containing a member variable, func, that points to a MyClass member function.
struct MyBind {
MyBind(void (MyClass::*_func)(const XKeyEvent&))
: func(_func) {}
void (MyClass::*func)(const XKeyEvent&);
}
Declaration and populating of a vector that holds user-defined Keybinds.
// in my_class.hh
std::vector<MyBind*> my_binds_;
// in my_class.cc, constructor
my_binds_.push_back(new MyBind( &MyClass::do_this ));
my_binds_.push_back(new MyBind( &MyClass::do_that ));
At this point, everything compiles and runs.
Now, when I try to delegate work by iterating over the my_binds_ vector, things go wrong. It is worth noting that I've left out error handling and other member variable accesses for clarity.
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(my_bind->*func)(e); // erroneous line
}
}
This should be the correct syntax, but it fails to compile, stating error: ‘func’ was not declared in this scope (g++, similar error from clang++).
This is weird to me, as replacing the erroneous line of code with auto test = keybind->func; does compile.
What am I doing wrong? Is there a better way to handle user key bind definitions? Thanks!
It would be best to use std::function and forget about raw member-function pointers altogether. They will only bring you pain :)
The problem with you code is that you only have a pointer to a method but no object. Your bind struct should also store an object pointer to call the method on:
struct MyBind {
MyBind(MyClass *obj, void (MyClass::*_func)(const XKeyEvent&))
: obj(obj), func(_func) {}
MyClass *obj;
void (MyClass::*func)(const XKeyEvent&);
void operator()(const XKeyEvent& event) const
{
(obj->*func)(event);
}
}
And then use it like this:
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(*my_bind)();
}
}
I've added a call operator to the bind struct for convenience. Note that the ->* operator is applied to the object the method belongs to.
This is not an answer, rather a pointer to your answer or my so-question :)
You had to use
(this->*(my_bind->func))(e);
instead of:
(my_bind->*func)(e);
I have re-created your error msg and asked a question after many different attempts.
See this( pointer to your answer ;) ): How to call pointer to member function, which has been saved in a vector of custom struct?
MyBind holds the pointer to member function of some instance of MyClass. Therefore in order to call these function pointers, you need to explicitly tell using this keyword, for which instance of MyClass you want the func to be called.

Code simpler than lambda for a call in constructor that uses an output parameter function for initializing a const member

In the header, I have
class CSomeClass
{
const GUID m_guid;
public:
CSomeClass();
///...
}
And in the source file
CSomeClass::CSomeClass()
, m_guid(
[]() {
GUID g;
::CoCreateGuid(&g);
return g;
}()
)
{
}
As you know Guids can be used as identifications not meant to be changed. Given the ::CocreateGuid() function provides what I want as an output parameter, instead of returning it, I cannot use directly a simple call to the function for initializing the m_guid member field, that is constant.
So, a consequence of its constness, is that it must be initialized before the opening bracket in initializer list, and therefore not be simply assigned with a call to ::CocreateGuid() in the constructor body.
Is there a simpler way to initialize it than this lambda expression?
When the lambda expression is correct, I would use a helper function for that:
GUID create_guid()
{
GUID g;
::CoCreateGuid(&g);
return g;
}
CSomeClass::CSomeClass() : m_guid(create_guid()) {}
In addition, create_guid() has a meaning by itself and could be reused (even if making it a implementation detail is possible/correct).
You should consider wrapping the GUID in its own class:
class CGUID
{
public:
CGUID()
{
CoCreateGuid(m_guid);
}
const GUID& guid() const { return m_guid; }
// Maybe some useful functions:
bool operator==(const CGUID&) const;
private:
GUID m_guid;
};
Now you can use the above as a member:
class CSomeClass
{
const CGUID m_guid;
...
Here we abstract your pattern:
template<class A>
A co_make( HRESULT(*f)(A*) {
A a;
HRESULT hr = f(&a);
Assert(SUCCEEDED(hr));
if (!SUCCEEDED(hr))
throw hr;
return a;
}
CSomeClass::CSomeClass()
m_guid(
co_make(&::CoCreateGuid)
)
{}
where we detect failure and assert then throw if that is the case.
I'm not sure this is simpler.
Really, write a GUID make_guid() function, stick it in some header, and call it.
Your proposal is the simplest way to initialize the constant instance member.
Don't get scared of lambdas, as a matter of fact, in general it is a new style recommendation to use lambdas for complex initializations of constants and references because they share the property of only being initialized at the point of declaration (or instance member initialization in the initializer list).
Furthermore, your code triggers the "named return value optimization" and there is no copy construction at the return from the lambda.
The interface to CoCreateGuid is deficient because it requires an output argument.
If you insist on not using the lambda, I think the next most practical alternative is to, in the constructor body, de-constify using const_cast to pass it to CoCreateGuid.
Mind you that one you enter the body of a constructor the language considers all individual members to have been properly initialized, and will invoke destructors for them should an exception happens, this makes a very big difference whether something is initialized in the initializer list or left with a binary pattern of garbage.
Finally, unfortunately you can't just call CoCreateGuid with a de-constified reference to m_guid in the lambda, because the lambda will still return a value and that will overwrite the member. It is essentially the same as what you already wrote (with the exception of the default constructor of g)
It would be simpler if you declare m_guid as a mutable instance member as opposed to const. The difference is that mutable are like a const for users of a class but a perfectly fine lvalue within the class

Overloaded -> and *: how to access initial class?

I have a class Property containing a data of type Matrix and which overloads operators ->, * and &, Matrix being another class of mine. The overloads give direct access to the data, e.g.
Property myProp;
myProp->trace();
The above code allows to compute the trace of the matrix directly from the Property containing it and without having to first get the data: handy.
Now I want to add a callback to my Property which is called when the Property gets updated. To do so I would like to be able to write something like:
myProp->registerCallback(myCallback);
My problem is that operator-> returns a reference to the Matrix, hence registerCallback gets called on the matrix class, not on Property. As I also overloaded the other operators * and &, it seems I am no longer able to call a member functions from Property.
Hence my question: is there any trick to work with the basic type after an operator was overloaded to return another type?
Thanks a lot!
In C++11 there is std::addressof function. Also boost library provides addressof function.
Example:
#include <iostream>
#include <memory>
struct Data
{
void foo() {
std::cout << "Data::foo" << std::endl;
}
};
template <typename T>
class Property
{
public:
Property() : data(new T) {}
~Property() { delete data; }
T** operator &() {
return &data;
}
T* operator->() {
return data;
}
void foo() {
std::cout << "Property::foo" << std::endl;
}
private:
T *data;
};
int main()
{
Property<Data> p;
p->foo();
std::addressof(p)->foo();
}
You should still be able to call functions in Property with the . operator...
Property myProp;
myProp->trace();
myProp.registerCallback(myCallback);
You've got a minor misunderstanding. If you overload operator* and operator-> then you object is trying to work like a pointer. This situation comes up often with iterators. An iterator's methods are called with . like this.
I have no idea why you would want to overload operator&; to achieve the same thing as fasked's operator&, just use &(*myProp). Besides, &myProp should give you the address of myProp, not its contained object.

Syntax error of a pointer to member function

Salutations
I'm trying to use the std::sort algorithms on specials objects.
I got a list to sort and a binary function which give me a comparison:
Interesting part of B.cpp
void B::FindClosest(vector<A*> list)
{
bool (B::*ptr)(A*,A*) = &B::Closer;
sort(list.begin(),list.end(),(this->*ptr));
// some use of this sorted list
}
bool B::Closer(A* lhs ,A* rhs)
{
if(Distance(this,lhs)<Distance(this,rhs))
{
return true;
}
else
{
return false;
}
}
And B.h :
class B : public A
public:
void FindClosest(vector<A*>);
bool Closer(A*,A*);
This seems pretty simple but i can't figure out why it's not working.
It seems to me that i'm doing something wrong on pointer to member function but cant find out what.
Here is the error msg :
agglomerate.cpp:32: error: invalid use of non-static member function
I've tried some other way to get things to work but nothing.
I'm not bound to pointer to member function, if you got a simple / different way to do this you're welcome.
Thanks a lot,
Azhrilla
You cannot use such thing, you should use std::bind or boost::bind or lambda for this case, since sort third parameter should be callable object, that receive two objects of type T.
With std::bind it will be
using namespace std::placeholders;
sort(list.begin(), list.end(), std::bind(ptr, this, _1, _2));
This line:
bool (B::*ptr)(A*,A*) = &B::Closer;
Gets a point to the member function B. To call this function you then need a class instance to call it on (the member function needs to know which conrete instance of class data it can access etc). For example
(this->*ptr)(lhs, rhs)
Calls the member function of this. If you did
B anotherB;
bool (B::*ptr)(A*,A*) = &B::Closer;
(anotherB.*ptr)(lhs, rhs)
That would call the B::Closer function but this time using anotherB and not this (assuming this was not 'anotherB')
I'm not sure what...
(this->*ptr)
...evaluates to?, but it is the problem
I think the problem is that you cannot give sort() the class instance and the member function pointer... you can only give it the member function pointer and so it has no class instance on which to call this function.
As ForEveR suggests, you could usde std::bind so that you can convert from a function withfour parameters, hls, rhs, class-instance, member-pointer. bind one to 'this' and one to the desired member function, so that the result is a function that just needs lhs and rhs.

Getting different instances to communicate

Suppose I have two instances of the same class. The class has a pointer to some data, and I want the instances to exchange the pointers as part of some private function's algorithm, but without compromising the data to everybody else by giving a direct access to it through a public function.
My first idea was to add a static variable of type bool called exchange, and two methods: a private one: void requestExchange() and a public one: Data** respond().
requestExchange would set exchange to true, and will be immediately followed with respond() from the instance of choice, which will do the following:
if(exchange==true){
exchange=false;
return data;
}
else{return...?!
This was when I realized that I have no way of simulating "NO OP" since data may in fact be NULL, so supposedly everything goes as a response. Any ideas as to what can be done?
UPDATE: I thought a bit about it, and since the request-respond combo will only be called in the context where NULL as a result will be meaningful (exchange is most certainly true) I suppose I can simply return NULL and simulate a NO OP this way. To an outsider NULL as a result will be useless... But I'm still interested in suggestions. There must be a more well structured way of doing this.
Objects of the same class can access each others' private data directly. You often see this in copy constructors, for example.
Your description of the problem is not very clear. Why can't you just make respond() a private function?
The idea with a static class member is fraught with peril. What if two pairs of such instances want to communicate simultaneously? What if one sets the exchange flag and then dies before it comes around to calling respond()? What about thread safety?
As for returning a NO-OP or error indicator, you can either use exceptions (that's what they are for, but if your project does not use exceptions it's not a good idea to introduce them suddenly), or go the route of boost::optional.
Might be best to separate your concerns with regards to returning the data and exchanging it.
class Foo
{
public:
Bar* data()
{
return pData;
}
private:
void exchangeData(Foo& Rhs)
{
if (this != &Rhs)
{
Bar* pTmp = pData;
pData = Rhs.pData;
Rhs.pData = pTmp;
}
}
Bar* pData;
}
Hopefully it's along the lines of what you want? The question isn't super clear....
I probably missed the point of your question. Why does this not do what you want?
class CMyClass
{
public:
void ExchangePointerWith( CMyClass& rhs );
private:
void* m_MyPtr;
};
and:
void CMyClass::ExchangePointerWith(CMyClass &rhs)
{
void* tmp= m_MyPtr;
m_MyPtr= rhs.m_MyPtr;
rhs.m_MyPtr= tmp;
}
Use std::swap() and build your class's own swap method then you know it should be exception safe. And swap() is a standard routing that most class should implement to make them efficient for the STL.
Remember that a class is automatically a friend of itself. So it can access the private member variables of another instance of the same class. See (Friend scope in C++)
#include <algorithm>
class myX
{
public:
void swap(myX& rhs) throw()
{
std::swap(data,rhs.data);
}
private:
void* data;
};