我正在利用我的 python/pyqt4 经验学习 C++(通过 Qt4),但我似乎无法掌握将 lambda 表达式存储到容器中以用作回调的正确习惯用法。
我有一个包含一堆字段的结构。我想创建一个回调映射,可以以特定方式正确格式化字段。
这是我想做的python等价物:
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')
起初我在 C++ 中找到了原生 lambdas 并开始尝试,但后来发现它显然是 C++11 的一个特性。编辑:在我开始调查是否可以将标志引入项目的构建系统之前,我想知道是否有 C++11 之前的方法。
然后我查看了boost解决方案。我的项目已经在使用 boost,所以我认为这可能是一个解决方案。我看到有lambda
和Phoenix
选项。为了表明我至少尝试过完成这项工作,这是我令人尴尬的失败:
## 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)));
在我写完最后一行之后,我意识到我正在转动我的轮子,最好向更多有经验的 C++ 开发人员询问创建 lambda 回调映射的惯用方法(与 Qt 兼容)。
我的目标是能够采用已知索引和已知AType
实例,并能够返回正确的格式QVariant
更新
根据接受的答案,这是我发现可行的解决方案。使用 C++98 兼容的解决方案。
#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"