能否从枚举类型构造std::initializer_list并用作函数默认参数?
核心结论
没办法直接动态构造std::initializer_list实例,它的设计初衷就是作为编译期常量列表的视图,不支持动态增改元素。不过你可以通过编译期模板生成的方式,做到只维护枚举定义、不用手动列所有枚举值,同时使用std::initializer_list或者更轻量的std::array作为参数。
方案1:C++20及以上推荐用
std::array(性能最优) std::array可以在编译期自动生成所有枚举值,完全不需要手动列,代码维护成本和你的vector方案一致,性能远高于动态生成的vector:
#include <iostream> #include <array> #include <utility> enum ID { A, B, C, D, MAX = D }; // 编译期生成包含所有连续枚举值的array template <typename Enum, Enum MaxVal> constexpr auto get_all_enum() { return [&]<std::size_t... I>(std::index_sequence<I...>) { return std::array<Enum, sizeof...(I)>{static_cast<Enum>(I)...}; }(std::make_index_sequence<static_cast<std::size_t>(MaxVal) + 1>{}); } inline constexpr auto all_id = get_all_enum<ID, ID::MAX>(); void func(const std::array<ID, all_id.size()>& args = all_id) { for (auto arg : args) { std::cout << arg << std::endl; } } int main() { func(); return 0; }
方案2:必须使用
std::initializer_list的兼容方案 如果你的函数参数必须是std::initializer_list类型,可以把它绑定到编译期生成的静态数组上,同样不需要手动列枚举值:
#include <initializer_list> #include <iostream> #include <utility> enum ID { A, B, C, D, MAX = D }; template <typename Enum, Enum MaxVal> constexpr std::initializer_list<Enum> get_all_enum() { static constexpr std::size_t count = static_cast<std::size_t>(MaxVal) + 1; static const Enum arr[] = [&]<std::size_t... I>(std::index_sequence<I...>) { return std::array<Enum, count>{static_cast<Enum>(I)...}; }(std::make_index_sequence<count>{}).data(); return {arr, arr + count}; } inline constexpr auto all_id = get_all_enum<ID, ID::MAX>(); void func(const std::initializer_list<ID>& args = all_id) { for (auto arg : args) { std::cout << arg << std::endl; } } int main() { func(); return 0; }
注意事项
以上所有方案都只适用于从0开始连续取值、最后一个值显式定义为MAX的枚举类型。如果你的枚举存在非连续的自定义值,没有办法自动生成所有取值列表,只能手动维护。
内容的提问来源于stack exchange,提问作者joaocandre
相关产品推荐
相关产品推荐

