gpt4 book ai didi

c++ - Python -> C++ 习语 : Storing lambda expressions in a map/container

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:04:10 24 4
gpt4 key购买 nike

我正在学习 C++(通过 Qt4)利用我的 python/pyqt4 经验,但我似乎无法掌握将 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++ 中发现了原生的 lambda 并开始尝试,但后来发现它显然是 C++11 的一个特性。 编辑:在开始调查是否可以将标志引入项目的构建系统之前,我想知道是否有 C++11 之前的方法。

然后我研究了 boost 解决方案。我的项目已经在使用 boost,所以我认为这可能是一个解决方案。我看到有两个 lambdaPhoenix选项。为了表明我至少已经尝试过这项工作,这是我令人尴尬的失败:

## 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"

最佳答案

在 C++ 中,lambda 只不过是语法糖,它允许您内联编写仿函数定义。 仿函数 是一个带有operator() 的对象。所以如果你不能使用 C++11(一个原因可能是因为你被迫使用旧的编译器?)那么你总是可以只定义仿函数类,或者如果那些概念性的 lambdas 没有捕获任何东西,那么你可以只使用普通的旧函数

:-)

凯,我要写一个例子。就几分钟...


开始了……

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()
{}

免责声明:未经测试的代码(除了它使用 msvc 和 mingw g++ 编译)。

关于c++ - Python -> C++ 习语 : Storing lambda expressions in a map/container,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13354729/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com