c++ - std::bind 与指向函数对象的指针

标签 c++ c++11 bind shared-ptr variadic-templates

给定一个指向函数对象的指针:

std::shared_ptr<std::function<double(double)>> f;

C++11 中是否有内置结构允许在 std::bind 语句中使用此指针?例如:

std::function<double()> g = std::bind(built_in(f), 0.0);

我正在做的是将可变参数模板用作:

template<typename Ret, typename... Args>
std::function<Ret(Args...)> get_fn(const std::shared_ptr<std::function<Ret(Args...)>>& f)
{
    return [=](Args... args) -> Ret { return (*f)(args...); };
}

这让我可以写:

std::function<double()> g = std::bind(get_fn(f), 0.0);

提前致谢。

编辑:我应该更清楚。为了优化目的,我需要在共享指针内使用函数对象的实例。

最佳答案

如果我们有一个用于解引用运算符的标准函数对象(很像 std::plus<T> 用于添加 TT ),那么我们可以涉及一个嵌套的绑定(bind)表达式,但事实并非如此——而且我们需要一个调用运算符,因为在评估嵌套绑定(bind)表达式期间发生的通常替换不适用于第一个参数!您的解决方案引入了额外的 std::function ,所以我提出了一些不需要的替代方案。

编写自己的调用和取消引用运算符:

struct call {
    template<typename Callable, typename... Args>
    auto operator()(Callable&& callable, Args&&... args) const
    // don't use std::result_of
    -> decltype( std::declval<Callable>()(std::declval<Args>()...) )
    { return std::forward<Callable>(callable)(std::forward<Args>(args)...); }
};

struct dereference {
    template<typename T>
    auto operator()(T&& t) const
    -> decltype( *std::declval<T>() )
    { return *std::forward<T>(t); }
};

template<typename IndirectCallable, typename... Args>
auto indirect_bind(IndirectCallable&& f, Args&&... args)
-> decltype( std::bind(call {}
                       , std::bind(dereference {}, std::declval<IndirectCallable>())
                       , std::declval<Args>()... ) )
{ return std::bind(call {}
                   , std::bind(dereference {}, std::forward<IndirectCallable>(f))
                   , std::forward<Args>()... ); }

然后你可以做 auto g = indirect_bind(f, 0.0); . Here's a proof-of-concept这也显示了如何适本地处理占位符。

我提到上面的解决方案是因为像 call 这样的仿函数和 dereference是有用的积木——我个人将它们放在我的工具中。然而,我的首选解决方案是编写一个多态仿函数来执行间接调用并一次性调用:

template<typename Indirect>
struct indirect_callable_type {
    // Encapsulation left as an exercise
    Indirect f;

    template<typename... Args>
    auto operator()(Args&&... args)
    // don't use std::result_of
    -> decltype( std::declval<Indirect&>()(std::declval<Args>()...) )
    { return f(std::forward<Args>(args)...); }

    template<typename... Args>
    auto operator()(Args&&... args) const
    // don't use std::result_of
    -> decltype( std::declval<Indirect const&>()(std::declval<Args>()...) )
    { return f(std::forward<Args>(args)...); }

    // Lvalue and rvalue *this version also left as an exercise
};

template<typename T>
indirect_callable_type<typename std::decay<T>::type>
make_indirect_callable(T&& t)
{ return { std::forward<T>(t) }; }

事实上,您可以将其用作 auto g = std::bind(make_indirect_callable(f), 0.0); .

我应该提一下,与您的解决方案不同,这些解决方案需要编写一些离线类型。由于 lambda 表达式的固有局限性,这是一种不幸的情况。如果你想坚持你目前拥有的东西,我有一个小建议,在 lambda 中你 std::forward<Args>(args)...参数。如果您曾经处理过仅移动类型,这可能会很有用。

关于c++ - std::bind 与指向函数对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13074315/

相关文章:

c++ - 如何将按钮连接到 ubuntu sdk 中的 FileDialog 函数?

c++ - 将 uint64_t 转换为 uint8_t[8]

c++ - 用等距值填充 std::vector<double> 的最简单方法

javascript - 我怎么知道什么时候在 JS 函数上使用 .bind()?

c++ - 关于英特尔的露天采矿示例

c++ - (C++11) 如果使用 cstdint 类型,g++ 不提供适当的警告 'incorrectly'

c++ - C++11 中的线程

C++11:v = { } 和 v { } 之间的区别

javascript - Python 替代 Javascript function.bind()?

jquery - 如何在新添加的 DOM 上创建实时点击事件