首页 \ 问答 \ 使用std :: apply应用可变参数函数(Applying a variadic function with std::apply)

使用std :: apply应用可变参数函数(Applying a variadic function with std::apply)

是否可以使用std :: apply将可变参数应用于元组?

例如,下面的代码在GCC 6.2.1中可以正常工作:

void print_t(std::string i, std::string j) {
    std::cout << i << " " << j << std::endl;
}

int main() {
        std::tuple<std::string, std::string> t{"ab", "cd"};
        std::experimental::apply(print_t, t);
        return 0;
}

但是,如果我尝试应用可变参数函数:

template<typename T>
void vprint(T && t) {
    std::cout << std::forward<T>(t) << std::endl;
}

template<typename T, typename ... Ts>
void vprint(T && t, Ts ... ts) {
    std::cout << std::forward<T>(t) << " ";
    vprint<Ts...>(std::forward<Ts>(ts)...);
}

int main() {
        std::tuple<std::string, std::string> t{"fd", "ab"};
        std::experimental::apply(vprint, t);
        return 0;
}

编译器会抱怨它无法推导出vprint模板参数。 好的,让我们明确地写出来:

std::experimental::apply(vprint<std::string, std::string>, t);

现在编译器结束了一些暴露标准库内部的晦涩错误。

我在C ++ 11中编写了自己的std::apply实现,并且理解为什么它不能推导出可变参数函数模板的参数。 但是, 从理论上讲std::apply具有所有扣除所需的信息。

那么在GCC6中,可变参数函数的应用还没有实现? C ++ 17兼容的编译器是否允许这样的应用程序? 如果没有,他们是否允许应用实例化的可变参数模板函数,如vprint<std::string, std::string>


Is it possible to apply a variadic function to a tuple with std::apply?

For example, the following code works fine with GCC 6.2.1:

void print_t(std::string i, std::string j) {
    std::cout << i << " " << j << std::endl;
}

int main() {
        std::tuple<std::string, std::string> t{"ab", "cd"};
        std::experimental::apply(print_t, t);
        return 0;
}

But if I try to apply a variadic function:

template<typename T>
void vprint(T && t) {
    std::cout << std::forward<T>(t) << std::endl;
}

template<typename T, typename ... Ts>
void vprint(T && t, Ts ... ts) {
    std::cout << std::forward<T>(t) << " ";
    vprint<Ts...>(std::forward<Ts>(ts)...);
}

int main() {
        std::tuple<std::string, std::string> t{"fd", "ab"};
        std::experimental::apply(vprint, t);
        return 0;
}

the compiler complains that it cannot deduce template arguments of vprint. OK, let's write them explicitly:

std::experimental::apply(vprint<std::string, std::string>, t);

Now the compiler ends up with some obscure errors which expose standard library internals.

I wrote my own implementation of std::apply in C++11 and I understand why it can't deduce arguments of the variadic function template. But, in theory, std::apply has all the information needed for that deduction.

So is the application of variadic functions a not yet implemented feature in GCC6? Will C++17-compatible compilers allow such application? If not, will they allow application of instantiated variadic template functions, like vprint<std::string, std::string>?


原文:https://stackoverflow.com/questions/40523334
更新时间:2023-07-24 14:07

最满意答案

Stephen Toub在他的博客上涵盖了所有各种方法及其相应的缺点

只有两种通用解决方案,两者都不理想:

  1. 复制图层中的逻辑; 让您的同步方法调用库中的同步方法。 (这假设库具有同步方法以及异步)。
  2. 阻止返回的任务,类似于您的示例代码。 这假设库始终使用ConfigureAwait(false) ,这是一个不受控制的假设。 如果库是无上下文的,那么将异步调用抛出到Task.Run并阻塞该任务可能会更安全。 此外,确保在阻止任务时解除异常,因为WaitResult将在AggregateException包装异常。

这两种解决方案都存在一些严重的维护问题。


Stephen Toub covers all the various approaches with their corresponding drawbacks on his blog.

There are only two general-purpose solutions, neither of which is ideal:

  1. Duplicate the logic in your layer; have your synchronous methods call the synchronous methods in the library. (This assumes that the library has synchronous methods as well as asynchronous).
  2. Block on the returned task, similar to your example code. This assumes that the library always uses ConfigureAwait(false), an assumption that is out of your control. If the library is context-free, then it may be safer to throw the asynchronous invocation into a Task.Run and block on that task instead. Also, ensure you unwrap exceptions when blocking on a task, since Wait or Result will wrap exceptions in an AggregateException.

Both of these solutions have somewhat serious maintenance problems.

相关问答

更多
  • 如图所示,从当前线程调用它是否是最佳做法? 如果当前线程在异步操作正在进行时是空闲的,为什么要使用不同的线程? 什么会使这个线程比你已经使用的更好? 想到有关DoIndependentWork实际上在做什么的问题。 如果它在HTTP请求完成之前完成至关重要,那么我会同步调用它。 如果在HTTP请求完成之前工作并不是至关重要的,那么我会寻找一个完全不同的解决方案。 在ASP.NET中使用Task.Run是很危险的。 请记住,ASP.NET中的延续在任意线程池线程上运行。 Is it the best prac ...
  • 首先避免使用异步void方法,因为你不能轻易等待它的完成。 相反,返回Task ,在async方法内,您不需要做一些特殊的事情来返回Task 。 编译器为您完成所有工作。 您需要等待对HttpClient.PostAsync的调用,这应该足以保持UI响应。 private static async Task CallService(System.Uri uri) { using (HttpClient client = new HttpClient()) { client.D ...
  • 这是一个解决方法,我发现,适用于所有情况(包括暂停调度员)。 这不是我的代码,我仍然在努力完全理解它,但它的工作。 可以使用: customerList = AsyncHelpers.RunSync>(() => GetCustomers()); 代码来自这里 public static class AsyncHelpers { /// /// Execute's an async Task method which has a voi ...
  • 您需要在同步方法的最后添加一些内容,以告诉它等待另一个呼叫完成。 我假设你的异步方法将有一个事件告诉调用者何时完成。 如果是这样的话,我会建议使用类似于ManualResetEvent的东西,在同步线程中等待它,并将其设置在异步的Finish事件接收器中。 例: public void DoSomething(Action actionToPerformOnComplete) { ManualResetEvent mre = new ManualResetEvent(false); D ...
  • 不要投票。 使用内置的同步功能。 RestResponse response = null; var executedCallBack = new AutoResetEvent(false); client.ExecuteAsync(request, (RestResponse aSyncResponse)=>{ response = aSyncResponse; executedCallBack.Set(); }); executedCallBack.WaitOne(); / ...
  • NSStream是一个抽象类,既不会将数据读取也不会将数据写入流中。 要实际访问数据,您需要一个具体的子类,例如NSInputStream或NSOutputStream (或NSOutputStream的自定义子类)。 要读取NSInputStream的数据,请调用read:maxLength: . 您可能希望使用hasBytesAvailable轮询流,询问是否有任何新数据可用。 NSOutputStream具有类似的write:maxLength:和hasSpaceAvailable方法。 iOS文档强 ...
  • 必须为async方法调用异步方法异步的单元测试? 不,但这样做是最自然的。 如果它使用Task.Run()同步调用异步方法,会丢失什么? 真的没什么。 它的性能稍差,但在某种程度上你可能永远不会注意到。 您可能希望使用GetAwaiter().GetResult()而不是Result来避免失败测试中的AggregateException包装。 你也可以直接调用这个方法; 无需将其包装在Task.Run 。 他们说这种缺乏支持是有正当理由的,我并不反对。 哦,我当然不同意他们。 :) 这是否意味着他们无法单元 ...
  • Stephen Toub在他的博客上涵盖了所有各种方法及其相应的缺点 。 只有两种通用解决方案,两者都不理想: 复制图层中的逻辑; 让您的同步方法调用库中的同步方法。 (这假设库具有同步方法以及异步)。 阻止返回的任务,类似于您的示例代码。 这假设库始终使用ConfigureAwait(false) ,这是一个不受控制的假设。 如果库是无上下文的,那么将异步调用抛出到Task.Run并阻塞该任务可能会更安全。 此外,确保在阻止任务时解除异常,因为Wait或Result将在AggregateException ...
  • 如果要编写异步代码,则应使用async / await 。 我在我的博客上有一个介绍,最后有一些后续资源。 当您启动异步操作(例如, Invoke )时,您将获得一个任务。 Task类型用于没有返回值的异步操作, Task用于具有返回值的异步操作。 这些任务类型可以在操作完成时指示您的代码,以及它是否成功完成或出错。 虽然你可以使用Task.Wait和Task.Result ,但我不推荐它们。 首先,它们在AggregateException包装任何异常,这使得您的错误处理代码更加麻烦。 使用a ...
  • 我建议您始终使用异步编程。 如果您遇到某种资源问题(即,不允许对单个数据库进行多次查询),那么您应该构建代码以便不会发生(例如,在操作正在运行时禁用UI按钮)。 或者,如果必须,您可以使用SemaphoreSlim来限制async代码: private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1); public async Task UploadCurrentXMLAsync() { await _mutex.WaitAsync(); t ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。