You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:16:16