C++17中如何实现指定模板:函数模板返回类型为第二模板参数
嘿,刚好C++17的特性完美解决这个需求,而且完全符合你要把F和V作为前两个模板参数的要求。咱们直接上代码,再一步步解释:
C++17 实现方案
核心思路是用std::invoke_result_t(C++17替代std::result_of的工具)自动推导可调用对象F的返回类型,然后把容器类型V作为第二个模板参数,默认值设为std::vector搭配F的返回类型。这样你既可以直接用默认的std::vector,也能随时替换成其他容器类型:
#include <functional> #include <vector> #include <list> #include <array> #include <iostream> // 模板参数顺序:F(可调用对象类型)、V(容器类型,默认是std::vector<F的返回类型>) // 用std::invoke_result_t自动获取F的返回类型,作为容器V的元素类型 template<typename F, typename V = std::vector<std::invoke_result_t<F>>> V generate_container(F&& func) { V container; // 针对固定大小容器(如std::array)做适配处理 if constexpr (std::is_same_v<V, std::array<std::invoke_result_t<F>, 1>>) { container[0] = std::forward<F>(func)(); } else { container.emplace_back(std::forward<F>(func)()); } return container; } // 测试示例 int main() { // 1. 默认使用std::vector,自动推导返回类型为int auto int_vec = generate_container([](){ return 42; }); std::cout << "Vector value: " << int_vec[0] << "\n"; // 2. 替换容器为std::list,元素类型自动匹配F的返回类型(std::string) auto str_list = generate_container([](){ return "Hello C++17!"; }, std::list<std::string>{}); std::cout << "List value: " << *str_list.begin() << "\n"; // 3. 替换为std::array(需要显式指定大小,元素类型自动匹配) auto int_arr = generate_container([](){ return 99; }, std::array<int, 1>{}); std::cout << "Array value: " << int_arr[0] << "\n"; return 0; }
关键细节解释:
std::invoke_result_t:这是C++17引入的特性,比旧的std::result_of更直观——你只需要传入可调用对象类型F,它就能直接给出调用F()后的返回类型,不需要像std::result_of那样写std::result_of_t<F()>这种冗余语法。- 模板默认参数:我们把
V的默认值设为std::vector<std::invoke_result_t<F>>,这样当用户只传F时,自动使用std::vector存储F的返回值;如果需要替换容器,只需要显式指定V的类型即可。 - 兼容性处理:对于
std::array这种固定大小的特殊容器,用C++17的if constexpr做针对性逻辑,避免编译错误,保证不同容器类型都能正常工作。
如果你的场景需要更复杂的容器初始化逻辑(比如传入初始大小、分配器等),还可以给函数添加额外参数传递这些信息,比如:
template<typename F, typename V> V generate_container(F&& func, const V& prototype) { V container = prototype; // 自定义初始化逻辑 container.emplace_back(std::forward<F>(func)()); return container; }
内容的提问来源于stack exchange,提问作者Edgard Lima
相关产品推荐
相关产品推荐

