C++11 存储不同类型的函数指针c++;boost::bind

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) 您

我今天在附近挖了不少,结果空无一人。有没有办法存储从不同类型的boost::bind返回的函子?我发现了一个使用boost::variants的示例,但不确定是否需要它。(为了简单起见,对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;
}