gpt4 book ai didi

C++ 函数接受给定模板签名的任何可调用对象

转载 作者:太空宇宙 更新时间:2023-11-04 12:52:01 26 4
gpt4 key购买 nike

如果我理解正确,编写接受任何可调用对象作为参数的函数的标准方法是:

template<typename Fn> void myFunction(Fn&& f) { ... }

我想做一些类似的事情,除了我想让 Fn 符合某个签名并且我需要知道它的参数类型。例如,像这样的东西:

template<typename T> void myFunction(std::function<void (T)>&& f) { ... }

问题是这不能接受 packaged_task 或捕获仅移动类型的 lambda,例如 std::promise


更新:添加了示例用例

考虑一个简化的网络请求函数:

template<typename T> void get(const Url& url,
const UrlQuery& params,
std::function<void (T)>&& callback) {
auto response = doGet(url, query);
callback(fromJson<T>(response));
}

这在大多数情况下工作得相当好,但是当我尝试向它传递一个捕获 std::promise 的 lambda 时,它失败了。我可以使用一些解决方法来完成这项工作,但我想知道是否有更优雅的方法。更接近这个伪代码的东西:

template<typename Fn<T>>
void get(const Url& url,
const UrlQuery& params,
Fn<T>&& callback) {
auto response = doGet(url, query);
callback(fromJson<T>(response));
}

显然,这无法编译,但它有点显示了我想要的内容。

get 的主体中设置 T 参数,同时保持 Fn&& 样式参数(例如,不指定 std::functionstd::packaged_task 作为 callback 的类型)并且在调用 get 时也不需要跳过任何步骤>.

最佳答案

以下解决不可复制的 lambda 部分,适用于 MinGW g++ 7.2 和 Visual C++ 2017:

#include <functional>       // std::function
#include <memory> // std::shared_ptr
#include <utility> // std::move

template< class Type >
void foo( std::function<void (Type)>&& f )
{
f( 42 );
}

struct No_copy
{
No_copy( No_copy const& ) = delete;
auto operator=( No_copy const& ) -> No_copy& = delete;

No_copy() {}
No_copy( No_copy&& ) {}
auto operator=( No_copy&& ) -> No_copy& { return *this; }
};

template< class Type >
class Copyable
{
std::shared_ptr<Type> pf_;

public:
template< class... Args >
auto operator()( Args&&... args )
{ return (*pf_)( std::forward<Args>( args )... ); }

Copyable( Type&& o )
: pf_{ std::make_shared<Type>( std::move( o ) ) }
{}
};

// Necessary for Visual C++ 2017:
template< class Type >
auto copyable( Type&& o ) { return Copyable<Type>{ std::move( o ) }; }

#include <iostream>
using namespace std;
auto main()
-> int
{
No_copy o;
#ifdef DETAILED
auto lambda = [oh{move(o)}]( int x ){ cout << x << " " << &oh << endl; };
auto const c = copyable( move( lambda ) );
foo<int>( c );
#else
foo<int>( copyable( [oh{move(o)}]( int x ){ cout << x << " " << &oh << endl; } ) );
#endif
}

不过,我还没有尝试过你提到的特定类型。

此外,此代码未解决推导参数类型的问题,如果您需要的话(如果需要,您必须添加此类推导)。

而且,嗯,还有可能的引用返回类型的问题,这里也没有解决。

:)

关于C++ 函数接受给定模板签名的任何可调用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48654726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com