2

我有一个通用功能:

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) : error C2665: 'boost::lambda::function_adaptor::apply' : 2 个重载都不能转换所有参数类型”。

我在这里做错了什么?

顺便提一句

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

3 回答 3

4

您是否碰巧在使用 lambda 的代码中使用了 #include boost/bind.hpp?这将导致对占位符(_1、_2 等)的不合格使用解析为由 Boost.Bind 定义的那些,并且这些与 Boost.Lambda 不能很好地混合。

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

于 2009-04-17T19:57:36.837 回答
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<_Ty1,_Ty2>::pair' :3 个重载都不能转换所有参数类型

错误。

当然你可以使用:

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

ExpressButtonPressed (func);

这更清晰并且可以编译

于 2009-04-17T12:52:21.243 回答
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
    )
);

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

于 2009-04-17T12:58:49.527 回答