如何用C++17实现仅接受特定类型的可变参数函数重载?
在C++17中实现仅接受特定类型参数的可变参数函数重载
需求说明
希望重载一个可变参数函数,让重载版本仅接受所有参数均为Bar类型的调用,其余情况使用通用版本。在C++20中可以通过约束缩写快速实现:
#include <type_traits> #include <iostream> // 通用版本 void foo(auto const&...) { std::cout << "default\n"; } struct Bar {}; // 仅接受全为Bar类型参数的重载 void foo(std::same_as<Bar> auto const&...){ std::cout << "Bar\n"; }
现在需要在C++17中实现相同效果,且不修改通用版本。
C++17实现方案
利用SFINAE机制,结合std::conjunction和std::is_same来筛选符合条件的参数列表,具体代码如下:
#include <type_traits> #include <iostream> // 通用版本,无需修改 void foo(auto const&...) { std::cout << "default\n"; } struct Bar {}; // C++17专属重载:仅匹配所有参数均为Bar的调用 template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Args, Bar>...>>> void foo(const Args&...) { std::cout << "Bar\n"; } // 测试用例 int main() { Bar b1, b2; foo(b1, b2); // 输出 "Bar" foo(b1, 42); // 输出 "default" foo(); // 输出 "Bar"(空参数包满足"所有参数都是Bar"的条件) }
代码解释
std::conjunction_v<std::is_same<Args, Bar>...>会对每个参数类型与Bar的匹配结果做逻辑与运算,只有所有参数都等于Bar时,表达式结果为true,触发SFINAE启用该重载。- C17不支持C20的约束缩写语法,因此必须显式声明模板参数
Args...,并通过默认模板参数实现SFINAE筛选。
可选调整:排除空参数包
如果希望空参数包调用通用版本,可以在条件中增加参数数量判断:
template<typename... Args, typename = std::enable_if_t<std::conjunction_v<std::is_same<Args, Bar>...> && (sizeof...(Args) > 0)>> void foo(const Args&...) { std::cout << "Bar\n"; }
内容的提问来源于stack exchange,提问作者joergbrech
相关产品推荐
相关产品推荐

