C++11 存储不同类型的函数指针c++;boost::bind
我今天在附近挖了不少,结果空无一人。有没有办法存储从不同类型的boost::bind返回的函子?我发现了一个使用boost::variants的示例,但不确定是否需要它。(为了简单起见,对Foo和Bar进行了简化)C++11 存储不同类型的函数指针c++;boost::bind,c++11,function-pointers,boost-bind,boost-variant,C++11,Function Pointers,Boost Bind,Boost Variant,我今天在附近挖了不少,结果空无一人。有没有办法存储从不同类型的boost::bind返回的函子?我发现了一个使用boost::variants的示例,但不确定是否需要它。(为了简单起见,对Foo和Bar进行了简化) #包括 #包括 #包括 #包括 #包括 模板 结构Foo{ const FooType tmp_值; Foo(const FooType&tmp_2;): tmp_值(tmp_) { } 模板 void运算符()(对象和操作数) { std::cout有多态函子(Foo和Bar) 您
#包括
#包括
#包括
#包括
#包括
模板
结构Foo{
const FooType tmp_值;
Foo(const FooType&tmp_2;):
tmp_值(tmp_)
{
}
模板
void运算符()(对象和操作数)
{
std::cout有多态函子(Foo和Bar)
您希望为某一组操作数类型键入擦除。我建议为此定义一个类型擦除函子类型:
struct ErasedFunctor
{
template<typename F> ErasedFunctor(F&& f)
: pimpl(new impl_<F>(std::forward<F>(f))) {}
template <typename T>
void operator()(T& oper) const {
assert(pimpl);
pimpl->call(oper);
}
private:
typedef boost::variant<int32_t&, int64_t&, double&, float&> Operand;
struct base_ { virtual void call(Operand oper) const = 0; };
// struct impl_ : base_ ...
std::shared_ptr<base_> pimpl;
};
印刷品
5
void ErasedFunctor::apply::operator()(const F&, T&) const [with F = Foo<double>; T = double](5)
5
6
void ErasedFunctor::apply::operator()(const F&, T&) const [with F = Bar<int>; T = double](6)
6
5
5
void ErasedFunctor::apply::operator()(常数F&,T&)常数[with F=Foo;T=double](5)
5.
6.
void ErasedFunctor::apply::operator()(常数F&,T&)常数[with F=Bar;T=double](6)
6.
5.
查看它
有关更多背景信息,请参见:
全样本
#包括
#包括
#包括
模板结构Foo{
const FooType tmp_值;
Foo(constfootype&tmp_uu):tmp_u值(tmp_u){}
模板无效运算符()(对象和操作数)常量{
std::我不这么认为,但我不确定是否可以作为答案发布。问题是您从未实际从变量中检索值。您需要使用apply\u visitor
或对其使用get()
。再看一遍。您正在尝试应用()
运算符,而不是它所包含的内容。这有很大帮助。不过我有一个问题。是否有办法扩展橡皮擦计数器,以包括对在初始化时使用2个元素而不是1个元素的结构的调用(如Foo和Bar或Baz(2,1.2))?它已经被支持。ErasedFunction
只关心可调用函数的算术性:我想我应该准确地包含我传递的内容。Baz(std::normal_distribution(0.0,3.0),std::mt19937(10))
这似乎引起了一点问题。我尝试扩展操作数,但没有清除任何内容。再次感谢@sehe@PeterHubner的帮助。@sehe@PeterHubner我不确定是什么阻止你修改Coliru上的示例:。sehe,再次感谢。我间隔了,甚至没有想更新示例。你的答案很准确。
struct ErasedFunctor
{
template<typename F> ErasedFunctor(F&& f)
: pimpl(new impl_<F>(std::forward<F>(f))) {}
template <typename T>
void operator()(T& oper) const {
assert(pimpl);
pimpl->call(oper);
}
private:
typedef boost::variant<int32_t&, int64_t&, double&, float&> Operand;
struct base_ { virtual void call(Operand oper) const = 0; };
// struct impl_ : base_ ...
std::shared_ptr<base_> pimpl;
};
typedef std::map<std::string, ErasedFunctor> test_map;
test_map createFunMap() {
return test_map {
{ "foo", Foo<double>(1.0) },
{ "bar", Bar<int32_t>(1) },
};
}
int main() {
test_map myMap = createFunMap();
double t = 5.0;
std::cout << t << std::endl;
myMap.at("foo")(t);
std::cout << t << std::endl;
myMap.at("bar")(t);
std::cout << t << std::endl;
}
5
void ErasedFunctor::apply::operator()(const F&, T&) const [with F = Foo<double>; T = double](5)
5
6
void ErasedFunctor::apply::operator()(const F&, T&) const [with F = Bar<int>; T = double](6)
6
5
#include <boost/bind.hpp>
#include <boost/variant.hpp>
#include <iostream>
template <typename FooType> struct Foo {
const FooType tmp_value;
Foo(const FooType &tmp_) : tmp_value(tmp_) {}
template <typename Object> void operator()(Object &operand) const {
std::cout << operand << std::endl;
operand += tmp_value;
}
};
template <typename BarType> struct Bar {
const BarType tmp_value;
Bar(const BarType &tmp_) : tmp_value(tmp_) {}
template <typename Object> void operator()(Object &operand) const {
std::cout << operand << std::endl;
operand -= tmp_value;
}
};
struct ErasedFunctor
{
template<typename F> ErasedFunctor(F&& f)
: pimpl(new impl_<F>(std::forward<F>(f))) {}
template <typename T>
void operator()(T& oper) const {
assert(pimpl);
pimpl->call(oper);
}
private:
typedef boost::variant<int32_t&, int64_t&, double&, float&> Operand;
struct base_ { virtual void call(Operand oper) const = 0; };
struct apply : boost::static_visitor<void> {
template <typename F, typename T> void operator()(F const& f, T& v) const {
std::cout << __PRETTY_FUNCTION__ << "(" << v << ")\n";
f(v);
}
};
template <typename F> struct impl_ : base_ {
F f_;
impl_(F&& f) : f_(std::forward<F>(f)) { }
virtual void call(Operand oper) const override {
boost::apply_visitor(boost::bind(apply(), boost::cref(f_), _1), oper);
}
};
std::shared_ptr<base_> pimpl;
};
#include <map>
typedef std::map<std::string, ErasedFunctor> test_map;
test_map createFunMap() {
return test_map {
{ "foo", Foo<double>(1.0) },
{ "bar", Bar<int32_t>(1) },
};
}
int main() {
test_map myMap = createFunMap();
double t = 5.0;
std::cout << t << std::endl;
myMap.at("foo")(t);
std::cout << t << std::endl;
myMap.at("bar")(t);
std::cout << t << std::endl;
}