.dp-highlighter { font-family: "Consolas", "Monaco", "Courier New", Courier, monospace; font-size: 12px; background-color: #E7E5DC; width: 99%; overflow: auto; margin: 18px 0 18px 0 !important; padding-top: 1px; /* adds a little border on top when controls are hidden */ } /* clear styles */ .dp-highlighter ol, .dp-highlighter ol li, .dp-highlighter ol li span { margin: 0; padding: 0; border: none; } .dp-highlighter a, .dp-highlighter a:hover { background: none; border: none; padding: 0; margin: 0; } .dp-highlighter .bar { padding-left: 45px; } .dp-highlighter.collapsed .bar, .dp-highlighter.nogutter .bar { padding-left: 0px; } .dp-highlighter ol { list-style: decimal; /* for ie */ background-color: #fff; margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */ padding: 0px; color: #5C5C5C; } .dp-highlighter.nogutter ol, .dp-highlighter.nogutter ol li { list-style: none !important; margin-left: 0px !important; } .dp-highlighter ol li, .dp-highlighter .columns div { list-style: decimal-leading-zero; /* better look for others, override cascade from OL */ list-style-position: outside !important; border-left: 3px solid #6CE26C; background-color: #F8F8F8; color: #5C5C5C; padding: 0 3px 0 10px !important; margin: 0 !important; line-height: 14px; } .dp-highlighter.nogutter ol li, .dp-highlighter.nogutter .columns div { border: 0; } .dp-highlighter .columns { background-color: #F8F8F8; color: gray; overflow: hidden; width: 100%; } .dp-highlighter .columns div { padding-bottom: 5px; } .dp-highlighter ol li.alt { background-color: #FFF; color: inherit; } .dp-highlighter ol li span { color: black; background-color: inherit; } /* Adjust some properties when collapsed */ .dp-highlighter.collapsed ol { margin: 0px; } .dp-highlighter.collapsed ol li { display: none; } /* Additional modifications when in print-view */ .dp-highlighter.printing { border: none; } .dp-highlighter.printing .tools { display: none !important; } .dp-highlighter.printing li { display: list-item !important; } /* Styles for the tools */ .dp-highlighter .tools { padding: 3px 8px 3px 10px; font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; background-color: #f8f8f8; padding-bottom: 10px; border-left: 3px solid #6CE26C; } .dp-highlighter.nogutter .tools { border-left: 0; } .dp-highlighter.collapsed .tools { border-bottom: 0; } .dp-highlighter .tools a { font-size: 9px; color: #a0a0a0; background-color: inherit; text-decoration: none; margin-right: 10px; } .dp-highlighter .tools a:hover { color: red; background-color: inherit; text-decoration: underline; } /* About dialog styles */ .dp-about { background-color: #fff; color: #333; margin: 0px; padding: 0px; } .dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; } .dp-about td { padding: 10px; vertical-align: top; } .dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; } .dp-about .title { color: red; background-color: inherit; font-weight: bold; } .dp-about .para { margin: 0 0 4px 0; } .dp-about .footer { background-color: #ECEADB; color: #333; border-top: 1px solid #fff; text-align: right; } .dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; color: #333; width: 60px; height: 22px; } /* Language specific styles */ .dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; } .dp-highlighter .string { color: blue; background-color: inherit; } .dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; } .dp-highlighter .preprocessor { color: gray; background-color: inherit; }

Friday, December 25, 2009

Binding to member variables.

When we use boost::bind to bind to a member function, things are pretty easy. You're making a function object of a usually stand-alone or a member function. But when you bind to a member variable of a class, things get a little hazy. When binding to a member variable, usually, you get a member pointer to the type of the member variable. And if you are using this bind in the context of a STL algorithm, then you apply this data member pointer to the passed in argument. This makes absolutely no sense, but see the code below, and it will hopefully make more sense.


struct entry
{
typedef std::pair<int, bool> conn_type;
entry(int i, bool c) : conn_pair(i, c ) { }
// bool get_connecting() const { return connecting; }
conn_type conn_pair;
};

int main()
{
std::vector<entry> vec;
vec.push_back(entry(1, false));
vec.push_back(entry(2, false));
vec.push_back(entry(3, true));
vec.push_back(entry(4, false));


/// boost::bind(&entry::connecting, _1
/// Make a function object that willa lways return ***connecting***
/// member variable of the passed in object...
/// make a predicate that returns entry::connecting
/// create a member pointer. In this case of type
/// entry::*connectingPtr = &entry::connecting
/// returns _1.*connecting

if(std::find_if(vec.begin(), vec.end(), boost::bind(
&std::pair<int, bool>::second,
boost::bind(&entry::conn_pair, _1))) != vec.end())
{
std::cout << "Hey. Found one" << std::endl;
bool std::pair<int, bool>::*connectingPtr = &std::pair<int, bool>::second;
std::cout << std::boolalpha << vec.front().conn_pair.*connectingPtr << std::endl;
}

return 0;
}


And if you are one of those who think pointers to data members are not useful, think again. The benefit of them is that once you declare a pointer to point to a data member of a type, you can use on different instances of that type. This link explains it clearly: http://stackoverflow.com/questions/670734/c-pointer-to-class-data-member

int main()
{
int Car::*pSpeed = &Car::speed;
Car myCar;
Car yourCar;

//access different instances using the same pointer.
int mySpeed = myCar.*pSpeed;
int yourSpeed = yourCar.*pSpeed;

assert(mySpeed > yourSpeed); // ;-)

return 0;
}



You might argue that you can always add a getter function that returns to you the value you pointed to, and do without pointers headaches. Not so. Like I showed in the example above, sometimes you are using pre-existing classes, like std::pair, and have no better way to have succinct code, except to bind. Oh well.