VS2022下模板版并行快排调用std::async触发C1001错误求助
问题描述
环境:Visual Studio 2022 v143,编译标准/std:c++20
将parallel_quick_sort实现为模板函数时,编译器抛出C1001(内部编译器错误),但非模板版本(如处理std::list<double>的版本)可正常编译运行。此前曾成功使用模板+std::async实现累加功能,无法定位当前问题原因。
模板版代码
template<typename T> std::list<T> parallel_quick_sort(std::list<T> input) { //std::cout << std::this_thread::get_id() << std::endl; if (input.size() < 2) { return input; } //move first element in the list to result list and take it as pivot value std::list<T> result; result.splice(result.begin(), input, input.begin()); T pivot = *result.begin(); //partition the input array auto divide_point = std::partition(input.begin(), input.end(), [&](T const& t) {return t < pivot; }); //move lower part of the list to separate list so that we can make recursive call std::list<T> lower_list; lower_list.splice(lower_list.end(), input, input.begin(), divide_point); auto new_lower(parallel_quick_sort<T>(std::move(lower_list))); //apply async to recrusive std::future<std::list<T>> new_upper_future(std::async(std::launch::async|std::launch::deferred, ¶llel_quick_sort, std::move(input))); result.splice(result.begin(), new_lower); result.splice(result.end(), new_upper_future.get()); return result; }
非模板版代码
std::list<double> parallel_quick_sort(std::list<double> input) { //std::cout << std::this_thread::get_id() << std::endl; if (input.size() < 2) { return input; } //move first element in the list to result list and take it as pivot value std::list<double> result; result.splice(result.begin(), input, input.begin()); double pivot = *result.begin(); //partition the input array auto divide_point = std::partition(input.begin(), input.end(), [&](double const& t) {return t < pivot; }); //move lower part of the list to separate list so that we can make recursive call std::list<double> lower_list; lower_list.splice(lower_list.end(), input, input.begin(), divide_point); auto new_lower(parallel_quick_sort(std::move(lower_list))); std::future<std::list<double>> new_upper_future(std::async(std::launch::async | std::launch::deferred, ¶llel_quick_sort, std::move(input))); result.splice(result.begin(), new_lower); result.splice(result.end(), new_upper_future.get()); return result; }
错误原因
模板版代码中调用std::async时,传递的函数地址¶llel_quick_sort是未特化的模板函数。std::async无法自动推导模板参数T,导致编译器在处理模板实例化和异步函数包装的逻辑时出现内部错误,触发C1001。
而非模板版本中,函数地址指向明确的具体函数,不存在参数推导问题,因此可以正常编译。
修复方案
方法1:显式指定模板参数
修改std::async的函数参数,明确指定模板实例化版本:
std::future<std::list<T>> new_upper_future( std::async(std::launch::async|std::launch::deferred, ¶llel_quick_sort<T>, std::move(input)));
这样编译器能直接确定要调用的模板特化函数,避免推导失败引发的内部错误。
方法2:用Lambda包装函数调用
用Lambda表达式封装模板函数调用,让std::async直接执行Lambda,绕开模板函数地址的推导问题:
std::future<std::list<T>> new_upper_future( std::async(std::launch::async|std::launch::deferred, [input = std::move(input)]() mutable { return parallel_quick_sort(std::move(input)); }));
Lambda会自动捕获当前模板参数T的上下文,无需显式指定,代码更简洁。
方法3:使用std::bind绑定模板参数
通过std::bind绑定模板参数,明确目标函数的类型:
std::future<std::list<T>> new_upper_future( std::async(std::launch::async|std::launch::deferred, std::bind(¶llel_quick_sort<T>, std::move(input))));
此方式同样能让编译器明确要调用的模板实例,解决内部编译错误。
内容的提问来源于stack exchange,提问作者Makise Kurisu
相关产品推荐
相关产品推荐

