Boost.Bind 访问 std::for_each 中的 std::map 元素

发布于 2024-08-23 05:37:33 字数 924 浏览 14 评论 0 原文

我有一个映射,它存储一个带有键的简单结构。该结构体有两个成员函数,一个是 const,另一个不是。我已经成功地使用 std::for_each 调用 const 函数,没有任何问题,但调用非常量函数时遇到了一些问题。

struct MyStruct {
  void someConstFunction() const;
  void someFunction();
};

typedef std::map<int, MyStruct> MyMap;
MyMap theMap;

//call the const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someConstFunction, boost::bind(&MyMap::value_type::second, _1)));

//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someFunction, boost::bind(&MyMap::value_type::second, _1)));

对 const 成员函数的调用工作正常,但 boost 内部似乎需要 const MyStruct 某处,因此在 MSVC7.1 中失败并出现以下编译错误。

boost\bind\mem_fn_template.hpp(151):错误 C2440:“参数”:无法从“const MyStruct *__w64”转换为“MyStruct *const”

我很感激任何关于如何正确设置模板参数的帮助,所以绑定确实正确识别参数并让我调用非常量函数。

谢谢, 卡尔

I've got a map that stores a simple struct with a key. The struct has two member functions, one is const the other not. I've managed calling the const function using std::for_each without any problems, but I've got some problems calling the non-const function.

struct MyStruct {
  void someConstFunction() const;
  void someFunction();
};

typedef std::map<int, MyStruct> MyMap;
MyMap theMap;

//call the const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someConstFunction, boost::bind(&MyMap::value_type::second, _1)));

//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someFunction, boost::bind(&MyMap::value_type::second, _1)));

The call to the const member function works fine, but it seems boost internally expects a const MyStruct somewhere, and thus fails with the following compilation error in MSVC7.1.

boost\bind\mem_fn_template.hpp(151): error C2440: 'argument' : cannot convert from 'const MyStruct *__w64 ' to 'MyStruct *const '

I'd appreciate any help on how to set the template parameters correctly, so bind does recognize the parameters correctly and let me call the non const function.

thanks,
Carl

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小…红帽 2024-08-30 05:37:33

IIRC,Boost.Bind 使用 boost::mem_fn 来绑定到成员功能。现在,如果您查看 mem_fun (向下滚动到 // data member support 部分),您将看到它将其 result_type 定义为 const&,同时仍然具有支持提取非常量成员的函数调用运算符的重载来自非常量参数。

因此,问题似乎在于这混淆了 Boost.Bind 的返回类型推导机制。因此,解决方案将明确告诉 Bind 结果不是 const:

//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someFunction, 
       boost::bind<MyStruct&>(&MyMap::value_type::second, _1)
   )
);

IIRC, Boost.Bind uses boost::mem_fn for its binding to members capability. Now, if you look at mem_fun (scroll down to the // data member support part), you'll see that it typedefs its result_type as a const&, while is still has overloads of the function call operator supporting the extraction of a non-const member from a non-const argument.

It thus seems that the problem is that this confuses Boost.Bind's return type deduction mechanism. A solution would thus to explicitly tell Bind that the result is not const:

//call the non-const member function
std::for_each(theMap.begin(), theMap.end(),
   boost::bind(&MyStruct::someFunction, 
       boost::bind<MyStruct&>(&MyMap::value_type::second, _1)
   )
);
梦境 2024-08-30 05:37:33

如果您发现自己必须经常这样做,我建议您使用 Boost.RangeEx 库:

#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/mem_fn.hpp>
#include <map>

struct MyStruct {
  void someConstFunction() const;
  void someFunction();
};

typedef std::map<int, MyStruct> MyMap;
MyMap theMap;

int main()
{
    //call the const member function
    boost::for_each(theMap | boost::adaptors::map_values,
                    boost::mem_fn(&MyStruct::someConstFunction));

    //call the non-const member function
    boost::for_each(theMap | boost::adaptors::map_values,
                    boost::mem_fn(&MyStruct::someFunction));
}

它已被 Boost 接受,但尚未随官方发行版一起提供。在此之前,您可以 ="noreferrer">Boost Vault(zip 文件的下载链接)。

If you find yourself having to do this a lot I recommend you use the Boost.RangeEx library:

#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/mem_fn.hpp>
#include <map>

struct MyStruct {
  void someConstFunction() const;
  void someFunction();
};

typedef std::map<int, MyStruct> MyMap;
MyMap theMap;

int main()
{
    //call the const member function
    boost::for_each(theMap | boost::adaptors::map_values,
                    boost::mem_fn(&MyStruct::someConstFunction));

    //call the non-const member function
    boost::for_each(theMap | boost::adaptors::map_values,
                    boost::mem_fn(&MyStruct::someFunction));
}

It's been accepted into Boost but it doesn't come with the official distribution yet. Until it does you can download it from the Boost Vault (download link to zip file).

木森分化 2024-08-30 05:37:33

如果您已经依赖 Boost,您可能愿意检查 Boost Foreach

BOOST_FOREACH(MyMap::value_type const& val, MyMap)
{
  val.second.someConstFunction();
}

可读性很强,但我不知道性能问题。

另请注意,如果不“转义” , 字符,则无法在宏中使用模板化类型:

  • 通过之前的 typedef
  • 或在类型周围使用第二对括号

If you are already depend on Boost, you may be willing to check Boost Foreach

BOOST_FOREACH(MyMap::value_type const& val, MyMap)
{
  val.second.someConstFunction();
}

Much much readable, though I don't know about performance issues.

Also note that you can't use templated typed within the macro without "escaping" the , character:

  • either by a typedef before
  • or by using a second pair of parenthesis around the type
双手揣兜 2024-08-30 05:37:33

我发现的一个问题:为非函数成员调用第二个绑定。第二个是数据成员,而不是 std::pair 的方法

One problem I spotted: the second bind is called for a non function member. second is a data member, not a method of std::pair

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文