8

如果给定的weak_ptr有效,我正在尝试创建一个在调用时执行 lambda/std::function 的辅助函数。目前以下代码有效,但不幸的是,它需要我定义模板参数。我正在寻找一种通过自动模板参数推导来做到这一点的方法。

template <typename DependentType, typename... ArgumentTypes>
auto make_dependent(std::weak_ptr<DependentType>& dependent, std::function < void(ArgumentTypes...)> functor) -> decltype(functor)
{
    return [&dependent, functor] (ArgumentTypes... args)
    {
        if (!dependent.expired()) {
            functor(args...);
        }
    };
};

理想情况下,我想std::function <void(ArgumentTypes...)>用通用模板参数替换FunctorType,但是我不确定如何从FunctorType. 上面的代码有效,下面的代码是理论上的:

template <typename DependentType, typename FunctorType>
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor) -> decltype(std::function<return_value(functor)(argument_list(functor))>)
{
    return[&dependent, functor](argument_list(functor) args)
    {
        if (!dependent.expired()) {
            functor(args...);
        }
    }
}

有没有办法做这样的事情?

4

3 回答 3

5

解决从参数中提取参数的问题的最简单方法是不从参数中提取参数。

template<typename F, typename C>
struct conditional_forwarder {
  F func;
  C cond;
  template<typename Fin, typename Cin>
  conditional_forwarder( Fin&& f, Cin&& c ):
    func(std::forward<Fin>(f)), cond(std::forward<Cin>(c)) {}
  template<typename... Args>
  void operator()( Args&&... args ) const {
    if (cond())
      func( std::forward<Args>(args)... );
  }
};
template<typename F, typename C>
conditional_forwarder< typename std::decay<F>::type, typename std::decay<C>::type >
make_conditional_forwarder( F&& f, C&& c ) {
  return {std::forward<F>(f), std::forward<C>(c)};
}
// todo: make_dependent_test   

template <typename DependentType, typename FunctorType>
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor)
  -> decltype(make_conditional_forwarder( make_dependent_test(dependent), functor) )
{
  return make_conditional_forwarder( make_dependent_test(dependent), functor);
}

这在 C++14 中会更容易。

顺便说一句,似乎存在一个基本的设计缺陷:条件转发器可能应该.lock()在.weak_ptrfunctorfunctor

当可以复制weak_ptra 的远程状态时,我也不确定您为什么持有对 a 的引用。weak_ptr

在 C++14 中,您可以返回如下内容:

return [=](auto&&... args) mutable {
}

我相信,这些decltype东西也主要是因为函数可以更容易地推断出它们的返回类型。

于 2013-07-30T23:54:45.393 回答
2

以下是我在 C++14 中解决问题的方法:

template<typename DependentType, typename FunctorType>
auto make_dependent(std::weak_ptr<DependentType> &dependent, FunctorType functor) {
  return [&dependent, functor](auto &&...args) {
    if (!dependent.expired())
      functor(std::forward<decltype(args)>(args)...);
  }
}

我在这里使用了两个 C++14 功能:

  • 推导出的返回类型make_dependent
  • 具有完美转发功能的可变参数泛型 lambda 以调用内部functor

编辑:dependent上面的代码通过引用捕获,就像您的原始代码一样。这真的是你想要的吗?

于 2013-08-01T06:10:37.273 回答
1

您可以使用代理特征类从单个模板参数中分别提取返回类型和参数。该类Trait使用静态函数dependent_func来创建要返回的 lambda。

template <typename DependentType, typename FunctorType>
struct Trait {};

template <typename DependentType, typename ReturnType, typename... ArgumentTypes>
struct Trait<DependentType, std::function<ReturnType(ArgumentTypes...)>> {
    static std::function<ReturnType(ArgumentTypes...)> dependent_func(const std::weak_ptr<DependentType>& dependent, std::function<ReturnType(ArgumentTypes...)>& functor) {
        return [&dependent, &functor] (ArgumentTypes... args) {
            if (!dependent.expired()) {
                return functor(args...);
            }
        };
    }
};

template <typename DependentType, typename FunctorType>
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType& functor) -> decltype(Trait<DependentType, FunctorType>::dependent_func(dependent, functor)) {
    return Trait<DependentType, FunctorType>::dependent_func(dependent, functor);
}

有关以这种方式解析模板参数的更多信息,请查看以下问题:C++ parsing function-type template argument

于 2013-07-31T00:42:20.857 回答