如何实现可接收指定T支持的所有std::initializer_list的模板类构造函数
有可落地的实现方案,核心思路是给AllInits加泛型构造函数,用编译期校验判断传入的std::initializer_list能否构造模板参数类型T,符合条件的重载就会生效。
C++20 及以上版本(最简实现)
直接用C++20的概念约束构造函数即可,代码可直接运行:
#include <initializer_list> #include <utility> #include <concepts> template <typename T> struct AllInits { // 泛型构造函数,仅当传入的initializer_list<U>能构造T时才会参与重载 template<typename U> requires std::is_constructible_v<T, std::initializer_list<U>> AllInits(std::initializer_list<U> init_list) { // 内部可直接用init_list构造T的实例,示例: T t(std::move(init_list)); // 其他业务逻辑 } }; struct ManyListTypes { ManyListTypes(std::initializer_list<bool>){} ManyListTypes(std::initializer_list<int>){} ManyListTypes(std::initializer_list<std::pair<int, int>>){} }; int main() { AllInits<ManyListTypes> first{true,false,true}; // 匹配bool类型的initializer_list重载 AllInits<ManyListTypes> second{1,2,3}; // 匹配int类型的initializer_list重载 AllInits<ManyListTypes> third{{1,1},{2,2},{3,3}}; // 匹配pair类型的initializer_list重载 return 0; }
C11~C17 兼容版本
如果用不了C++20的语法,可以用std::enable_if结合SFINAE做编译期约束,实现效果完全一致:
#include <initializer_list> #include <utility> #include <type_traits> template <typename T> struct AllInits { template<typename U> AllInits(std::initializer_list<U> init_list, typename std::enable_if<std::is_constructible<T, std::initializer_list<U>>::value, void>::type* = nullptr) { T t(std::move(init_list)); // 其他业务逻辑 } }; struct ManyListTypes { ManyListTypes(std::initializer_list<bool>){} ManyListTypes(std::initializer_list<int>){} ManyListTypes(std::initializer_list<std::pair<int, int>>){} }; int main() { AllInits<ManyListTypes> first{true,false,true}; AllInits<ManyListTypes> second{1,2,3}; AllInits<ManyListTypes> third{{1,1},{2,2},{3,3}}; return 0; }
两种实现都完全覆盖你示例中的所有调用场景,如果传入的initializer_list元素类型不在T支持的范围内,会在编译期直接报错,符合类型安全要求。
内容的提问来源于stack exchange,提问作者wehin19066
相关产品推荐
相关产品推荐

