所以,我正在写一个C ++程序,它可以让我控制整个世界。我写完了最后的翻译单元,但是我收到了一个错误:
error C3848: expression having type 'const `anonymous-namespace'::ElementAccumulator<T,BinaryFunction>' would lose some const-volatile qualifiers in order to call 'void `anonymous-namespace'::ElementAccumulator<T,BinaryFunction>::operator ()(const point::Point &,const int &)'
with
[
T=SideCounter,
BinaryFunction=std::plus<int>
]
c:\program files (x86)\microsoft visual studio 9.0\vc\include\functional(324) : while compiling class template member function 'void std::binder2nd<_Fn2>::operator ()(point::Point &) const'
with
[
_Fn2=`anonymous-namespace'::ElementAccumulator<SideCounter,std::plus<int>>
]
c:\users\****\documents\visual studio 2008\projects\TAKE_OVER_THE_WORLD\grid_divider.cpp(361) : see reference to class template instantiation 'std::binder2nd<_Fn2>' being compiled
with
[
_Fn2=`anonymous-namespace'::ElementAccumulator<SideCounter,std::plus<int>>
]
我查看了binder2nd
的规范,它是:它采用了const
AdaptibleBinaryFunction。
所以,我想,这不是什么大不了的事。我只是使用了boost::bind
,对吧?
错误!现在,我的接管世界程序需要很长时间才能编译(bind
在模板中使用,实例化得非常多)!按照这个速度,我的克星将首先接管世界!我不能让这种情况发生 - 他使用Java!
有人可以告诉我为什么做出这个设计决定?这似乎是一个奇怪的决定。我想我现在必须制作班级mutable
的一些元素......
编辑:违规代码:
template <typename T, typename BinaryFunction>
class ElementAccumulator
: public binary_function<typename T::key_type, typename T::mapped_type, void>
{
public:
typedef T MapType;
typedef typename T::key_type KeyType;
typedef typename T::mapped_type MappedType;
typedef BinaryFunction Func;
ElementAccumulator(MapType& Map, Func f) : map_(Map), f_(f) {}
void operator()(const KeyType& k, const MappedType& v)
{
MappedType& val = map_[k];
val = f_(val, v);
}
private:
MapType& map_;
Func f_;
};
void myFunc(int n)
{
typedef boost::unordered_map<Point, int, Point::PointHash> Counter;
Counter side_count;
ElementAccumulator<SideCounter, plus<int> > acc(side_count, plus<int>());
vector<Point> pts = getPts();
for_each(pts.begin(), pts.end(), bind2nd(acc, n));
}
答案 0 :(得分:5)
binder2nd
ctor对AdaptableBinaryFunction
- 而不是 const
AdaptableBinaryFunction
本身采用引用 。你的实例化代码怎么样?一个人通常没有明确提到binder2nd
,而是通过便利函数bind2nd(它只适用于第二个参数x
和typename Operation::second_argument_type(x)
等)。
答案 1 :(得分:0)
好吧,尝试一些演绎:
任何东西取任何东西的原因是允许某人将const传递给它。
您希望传递给“功能”函数的最明显的const是对临时函数的引用。
特别是,如果bind1st
和<functional>
中的其他内容采用非const引用参数,则无法将它们链接在一起以函数样式进行编程。功能样式憎恶在一个语句中捕获变量中的临时值的想法,然后“稍后”在“下一个”语句中修改该变量。所有非常迫切和副作用。
不幸的是,这意味着在定义<functional>
时,operator()
的仿函数在这种情况下需要是const,大概是其他一些情况。你的不是。
boost :: bind是否允许const
或者不作为模板类型的一部分?如果是这样,那么<functional>
可能不会这么做,因为一旦人们更多地了解如何充分利用模板,就会设计boost :: bind。或许bind1st
的设计具有更纯粹的功能性思维,因此没有副作用,因此为什么一切都不应该是常量?我可能已经错过了问题的一部分 - 我从你的代码示例中看到了为什么要使用参数绑定,但我认为很明显,名为<functional>
的标题是寻找的正确位置涉及累加器的任何事情; - )
答案 2 :(得分:0)
bind
(旧的,已弃用的bind1st
和bind2nd
)具有价值语义。返回对象是自包含的,它不会引用参数const
,而不是{。}}。
要获取引用语义,请将std::ref
传递给bind
。
auto defer_by_value = std::bind( fun, foo, bar ); // Copy fun, foo, and bar.
auto defer_by_ref = std::bind( std::ref( fun ), std::ref( foo ), std::ref( bar ) );
// Observe fun, foo, and bar.