C++折叠表达式实现参数包布尔运算及自动类型推导优化
问题分析
你的原代码核心问题有两个:一是必须显式指定模板类型T,无法自动推导;二是折叠表达式里的|| ... || false属于冗余写法——C++折叠表达式对||的空参数包默认结果就是false,直接写((ts == value) || ...)即可。
下面分别给出C17和C20的可行方案:
C++17 实现方案
C++17不支持auto作为非类型模板参数的类型,要省去显式指定T需要一些技巧,分两种场景:
场景1:候选值仍作为模板参数传递
我们可以用宏自动推导T的类型,避免手动写<int>这类标注:
#include <type_traits> template<typename T, T... Ts> constexpr bool is_in(T value) { // 折叠表达式:逐个匹配,只要有一个相等就返回true return ((Ts == value) || ...); } // 宏自动推导T为输入值的类型 #define IS_IN(value, ...) is_in<decltype(value), __VA_ARGS__>(value) int main() { if constexpr(IS_IN(1, 1, 2, 3)) { return 10; // 会执行,因为1在候选列表里 } return 0; }
场景2:候选值作为函数参数传递
如果允许把候选值放在函数参数里,就能直接实现自动类型推导,同时用static_assert确保所有候选值类型和输入值一致:
#include <type_traits> template<typename T, typename... Args> constexpr bool is_in(T value, Args... args) { // 强制所有候选值和输入值类型相同,避免隐式转换导致的意外 static_assert((std::is_same_v<T, Args> && ...), "所有候选值必须和输入值类型一致"); return ((args == value) || ...); } int main() { if constexpr(is_in(1, 1, 2, 3)) { return 10; } return 0; }
C++20 实现方案
C++20引入了auto非类型模板参数,直接解决了类型推导的问题,写法更加简洁:
严格类型匹配版
用requires约束确保所有候选值和输入值类型完全一致:
#include <concepts> template<auto... Ts> constexpr bool is_in(decltype(Ts) value) requires (std::same_as<decltype(Ts), decltype(value)> && ...) { return ((Ts == value) || ...); } int main() { if constexpr(is_in<1, 2, 3>(1)) { return 10; } return 0; }
宽松类型匹配版(支持隐式转换)
如果允许候选值和输入值进行隐式类型转换(比如is_in<1,2,3>(1.0)),可以去掉约束,用std::common_type_t统一类型:
#include <type_traits> template<auto... Ts> constexpr bool is_in(std::common_type_t<decltype(Ts)...> value) { return ((Ts == value) || ...); } int main() { if constexpr(is_in<1, 2, 3>(1)) { return 10; } return 0; }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

