如何利用推导指南或辅助函数简化std::array<std::pair<T, int>>类型数组的定义?
如何利用推导指南或辅助函数简化std::array<std::pair<T, int>>类型数组的定义?
嘿,这个需求太接地气了!谁不想少写点重复的std::pair,让代码看起来更清爽呢?下面我给你两种靠谱的解决方案,不管是用推导指南还是辅助函数都能完美搞定你的问题。
一、用推导指南实现(C++20+)
如果你用的是C++20或更高版本,我们可以给你定义的PairArray别名模板加一个推导指南,让编译器自动帮你推导类型T和数组大小size,完全不用手动写std::pair。
先上可直接运行的代码:
#include <array> #include <utility> // 先定义别名模板,固定pair的第二个类型为int template<typename T, std::size_t size> using PairArray = std::array<std::pair<T, int>, size>; // 给PairArray加推导指南,告诉编译器怎么从初始化列表推导出T和size template<typename T, std::size_t N> PairArray(std::initializer_list<std::pair<T, int>>) -> PairArray<T, N>; // 现在就能直接这么写了! int main() { PairArray my_pairs{ {1.23, 1}, {3.14, 2}, {7.89, 3}, }; // my_pairs的类型是PairArray<double, 3>,也就是std::array<std::pair<double, int>, 3> }
原理其实很简单:这个推导指南相当于给编译器递了个小纸条,告诉它“当我用一堆{值, int}这样的初始化器来初始化PairArray时,你自动把每个初始化器转成std::pair<T, int>,然后从第一个初始化器的第一个成员推导出T的类型,初始化器的数量就是数组的大小”。
如果你想让代码更严谨,还可以用C++20的概念(Concepts)加个约束,确保所有初始化器都能转换成std::pair<T, int>:
template<typename T, typename... Args> requires ((std::is_constructible_v<std::pair<T, int>, Args> && ...)) PairArray(Args&&...) -> PairArray<T, sizeof...(Args)>;
二、用辅助函数实现(兼容C++17+)
如果你的编译器还没升级到C++20,或者你觉得推导指南有点抽象,那写一个make_pair_array辅助函数是更稳妥的选择,兼容性更好,代码也更直观。
直接上可用的简洁版代码:
#include <array> #include <utility> // 辅助函数,接受初始化列表的初始化列表,自动推导类型和大小 auto make_pair_array(const std::initializer_list<std::pair<auto, int>>& init_list) { using T = std::decay_t<decltype(std::get<0>(*init_list.begin()))>; return std::array<std::pair<T, int>, init_list.size()>{init_list}; } // 测试代码 int main() { auto my_pairs = make_pair_array({ {1.23, 1}, {3.14, 2}, {7.89, 3} }); // my_pairs的类型是std::array<std::pair<double, int>, 3> }
这个写法里,编译器会自动把每个{1.23, 1}转换成std::pair<double, int>,整个大的初始化列表会被推导成std::initializer_list<std::pair<double, int>>,辅助函数再把它转换成对应的std::array。
如果你想要支持完美转发(避免不必要的拷贝),可以用这个版本:
#include <array> #include <utility> #include <initializer_list> template<typename T> auto make_pair_array(std::initializer_list<std::pair<T, int>>&& pairs) { return std::array<std::pair<T, int>, pairs.size()>(std::move(pairs)); } // 用法和上面完全一样
备注:内容来源于stack exchange,提问作者Nick Matteo
相关产品推荐
相关产品推荐

