如果给定的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...);
}
}
}
有没有办法做这样的事情?
答案 0 :(得分: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_ptr
,然后在该锁中执行functor
,以便前提条件(资源被保留)适用于functor
的整个调用。
当我可以复制weak_ptr
的远程状态时,我也不确定为什么要保留对weak_ptr
的引用。
在C ++ 14中,您可以返回类似的内容:
return [=](auto&&... args) mutable {
}
我相信,decltype
内容也会消失,因为函数可以更轻松地推断出它们的返回类型。
答案 1 :(得分: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
functor
编辑:上面的代码通过引用捕获dependent
,就像您的原始代码一样。这真的是你想要的吗?
答案 2 :(得分: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