问题嵌套boost :: lambda :: bind-s

时间:2009-04-17 09:27:20

标签: c++ boost-lambda

我有一个通用功能:

void ImageAlbum::ExpressButtonPressed(
    boost::function<
        void (
            thumb::PhotoPrintThumbnail*,
            thumb::PhotoPrintFormat,
            thumb::PhotoPrintQuantity
        )
    > memberToCall
) {
    ...

    BOOST_FOREACH(thumb::PhotoPrintThumbnail *pThumbnail, m_thumbs.GetSelected()) {
    memberToCall(
            pThumbnail,
            m_expressSel.GetSelectedFormat(),
            m_expressSel.GetSelectedQuantity()
        );
    }

    ...
}

我可以成功致电:

ExpressButtonPressed(boost::bind(&thumb::PhotoPrintThumbnail::AddQuantity, _1, _2, _3));

然后,我需要用一种格式替换它们,而不是将某种格式的数量添加到缩略图中。更精确的是,列表包含1个元素:

ExpressButtonPressed(
    boost::lambda::bind(
        &thumb::PhotoPrintThumbnail::SetFormats,
        _1,
        boost::lambda::bind(
            boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormats>(),
            1,
            boost::lambda::bind(
                boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormat>(),
                _2,
                _3
            )
        )
    )
);

导致“boost / lambda / detail / actions.hpp(96):错误C2665:'boost :: lambda :: function_adaptor :: apply':2个重载中没有一个可以转换所有参数类型”。< / p>

我在这里做错了什么?

顺便说一句

class PhotoPrintThumbnail {
public:
...
    typedef std::pair<PhotoPrintFormat, PhotoPrintQuantity> LoadedFormat;
    typedef std::list<LoadedFormat> LoadedFormats;
    void SetFormats(const LoadedFormats &formats);

3 个答案:

答案 0 :(得分:4)

你在lambda使用代码中碰巧#include boost / bind.hpp吗?这会导致占位符(_1,_2等)的无限制使用以解析为Boost.Bind定义的占位符,并且这些与Boost.Lambda不能很好地混合。

重写代码以显式使用boost :: lambda :: _ [1,2,3]而不是非限定名称在我的VC 7.1设置上编译得很好。

答案 1 :(得分:0)

不确定您使用的是什么版本的Boost或什么编译器。使用boost 1.37和VS2005,我可以得到相同的错误。我怀疑可能是模板扩展的核心错误导致了SFINAE问题。

例如,取出最里面的表达式:

boost::function<
    PhotoPrintThumbnail::LoadedFormat (
            PhotoPrintFormat,
            PhotoPrintQuantity
    )
> func = boost::lambda::bind
                ( boost::lambda::constructor<PhotoPrintThumbnail::LoadedFormat>()
                , _1
                , _2
                );

对我来说看起来还不错,但也失败了,尽管有一个:

std :: pair&lt; _Ty1,_Ty2&gt; :: pair':3个重载中没有一个可以转换所有参数类型

错误。

当然你可以使用:

void func
( PhotoPrintThumbnail* ppt
, const PhotoPrintFormat& ppf
, const PhotoPrintQuantity& ppq
)
{
    ppt->SetFormats (PhotoPrintThumbnail::LoadedFormats (1, PhotoPrintThumbnail::LoadedFormat (ppf, ppq)));
}

ExpressButtonPressed (func);

更清晰并编译

答案 2 :(得分:0)

我认为在第一次绑定时,你应该将构造的对象(由第二个绑定产生)绑定为方法的第一个参数(它应该是构造对象的地址):

ExpressButtonPressed(
    boost::lambda::bind(
        &thumb::PhotoPrintThumbnail::SetFormats,
        boost::lambda::bind(
                boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormats>(),
                1,
                boost::lambda::bind(
                        boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormat>(),
                        _2,
                        _3
                )
        ),
        _1
    )
);

我没有尝试编译代码。另一个可能的问题是第二个绑定仿函数可能会按值返回构造的对象,第一个绑定需要一个指向对象的指针(作为此指针),因此您仍需要一个指针作为SetFormats的第一个绑定参数。