Python & # 8594; C ++ idiom: storing lambda expressions in a map / container

I am learning C ++ (via Qt4) using my python / pyqt4 experience, and I cannot figure out the correct idiom for storing lambda expressions in a container for use as callbacks.

I have a structure with a bunch of fields. And I want to create a callback map that can correctly format fields in a certain way.

Here is the python equivalent of what I want to do:

from PyQt4.QtCore import QVariant, QString class AType(object): def __init__(self): self.name = "FOO" self.attr2 = "BAR" self.attr3 = "BAZ" # ... callbacks = {} callbacks['name'] = lambda x: QVariant(QString(x.name)) callbacks['attr2'] = lambda x: QVariant(QString(x.attr2)) callbacks['attr3'] = lambda x: QVariant(QString(x.attr3)) a = AType() variant = callbacks['name'](a) print variant.toString() # PyQt4.QtCore.QString(u'FOO') 

At first I found native lambdas in C ++ and started checking it out, but then I found that this is apparently a C ++ 11 function. Edit: I want to know if there is a preliminary C ++ 11 approach before I start investigating if I can enter a flag in the build system for the project.

Then I looked at the forced solutions. My project is already using boost, so I thought it might be a solution. I see that there are lambda and Phoenix options. To show that I at least tried to do this job, here is my embarrassing failure:

 ## my_class.h ## #include <QVariant> #include <QMap> #include <boost/function.hpp> QMap< uint, boost::function<QVariant (AType&)> > callbacks; ## my_class.cpp ## #include <boost/lambda/lambda.hpp> #include <boost/bind/bind.hpp> #include "my_class.h" // I invite you to laugh at this callbacks[0] = boost::bind(&QVariant, boost::bind(&QString::fromStdString, boost::bind(&AType::name, _1))); 

After I wrote this last line, I realized that I was spinning my wheels, and better just ask more experienced C ++ developers about the idiomatic approach to creating a lambda callback map (Qt compatible).

My goal is to be able to use the well-known index and known instance of AType and be able to return the correct QVariant format

Update

This is the solution that I found to work based on the accepted answer. Using a C ++ 98 compatible solution.

 #include <QMap> #include <QVariant> #include <QString> #include <QDebug> struct AType { AType(); std::string name, attr2, attr3; }; AType::AType() { name = "FOO"; attr2 = "BAR"; attr3 = "BAZ"; } typedef QMap< QString, QVariant (*)( AType const& ) > Callbacks; struct ATypeFieldMapper { static QVariant name( AType const& x ) { return QVariant(QString::fromStdString(x.name)); } static QVariant attr2( AType const& x ) { return QVariant(QString::fromStdString(x.attr2)); } static QVariant attr3( AType const& x ) { return QVariant(QString::fromStdString(x.attr3)); } }; int main() { Callbacks callbacks; callbacks["name"] = &ATypeFieldMapper::name; callbacks["attr2"] = &ATypeFieldMapper::attr2; callbacks["attr3"] = &ATypeFieldMapper::attr3; AType a; qDebug() << callbacks["name"](a).toString(); qDebug() << callbacks["attr2"](a).toString(); qDebug() << callbacks["attr3"](a).toString(); } //"FOO" //"BAR" //"BAZ" 
+4
source share
1 answer

In C ++, a lambda is nothing more than syntactic sugar that allows you to write inline functor definitions. A functor is an object with operator() . Therefore, if you cannot use C ++ 11 (one of the reasons may be because you have to use the old compiler?), Then you can always simply define functor classes, or if these conceptual lambdas do not capture anything, then you can just use simple old functions.

:-)

Kay, I'm going to write an example. Just a few minutes ...


Here goes & hellip;
 struct QString{ QString( wchar_t const* ){} }; struct QVariant { QVariant( QString const& ) {} }; struct AType{ wchar_t const* name() const { return L""; } }; #include <functional> // std::function #include <map> // std::map #include <string> // std::wstring using namespace std; void cpp11() { typedef map< wstring, function< QVariant( AType const& ) > > Callbacks; Callbacks callbacks; callbacks[L"name"] = []( AType const& x ) { return QVariant( QString( x.name() ) ); }; auto const a = AType(); auto variant = callbacks[L"name"]( a ); } void cpp03Limited() { typedef map< wstring, QVariant (*)( AType const& ) > Callbacks; Callbacks callbacks; struct SimpleConversion { static QVariant convert( AType const& x ) { return QVariant( QString( x.name() ) ); } }; callbacks[L"name"] = &SimpleConversion::convert; AType const a = AType(); QVariant const variant = callbacks[L"name"]( a ); } void cpp03General() { struct IConversion { virtual QVariant convert( AType const& ) const = 0; }; struct ConversionInvoker { IConversion const* pConverter; QVariant operator()( AType const& x ) const { return pConverter->convert( x ); } explicit ConversionInvoker( IConversion const* const p = 0 ) : pConverter( p ) {} }; typedef map< wstring, ConversionInvoker > Callbacks; Callbacks callbacks; struct SimpleConversion: IConversion { virtual QVariant convert( AType const& x ) const { return QVariant( QString( x.name() ) ); } }; SimpleConversion const simpleConversionFunc; callbacks[L"name"] = ConversionInvoker( &simpleConversionFunc ); AType const a = AType(); QVariant const variant = callbacks[L"name"]( a ); } int main() {} 

Disclaimer: Unverified code (except that it compiles using msvc and mingw g ++).

+3
source

Source: https://habr.com/ru/post/1445670/


All Articles