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

C++如何实现支持类型/非类型参数的类模板及自定义可调用get工具

核心限制说明

C++ 当前标准(截至 C++23)仅支持函数模板基于模板参数类别(类型参数/非类型参数)重载,变量模板、类模板均不支持该类重载,所以你无法直接实现MyClass<int>和MyClass<2>共享同一个类模板名的写法,也无法直接定义同名变量模板同时接受类型和非类型参数。

实现方案

方案1:直接重载函数模板(推荐)

如果你需要的是和std::get完全一致的调用形式myns::get<2>(tup)、myns::get<int>(tup),直接重载函数模板即可,写法最简单也没有额外开销:

#include <tuple>
#include <utility>

namespace myns {
// 匹配类型参数的重载
template <typename T>
constexpr decltype(auto) get(auto&& tup) {
    return std::get<T>(std::forward<decltype(tup)>(tup));
}

// 匹配索引非类型参数的重载
template <std::size_t I>
constexpr decltype(auto) get(auto&& tup) {
    return std::get<I>(std::forward<decltype(tup)>(tup));
}
}

调用示例:

std::tuple<int, std::string> sample_tup{10, "hello"};
// 按索引取
myns::get<0>(sample_tup); // 返回10
// 按类型取
myns::get<int>(sample_tup); // 返回10

方案2:支持独立可调用对象的妥协方案

如果你确实需要把get<2>/get<int>作为独立可调用对象传递(比如作为算法入参、赋值给变量),可以对类型参数做轻量包装来规避模板重载限制:

#include <tuple>
#include <utility>
#include <type_traits>

namespace myns {
template <typename T>
struct type_wrap { using type = T; };
// 类型包装工具
template <typename T>
constexpr type_wrap<T> t{};

template <auto Arg>
constexpr auto get = []<typename Tup>(Tup&& tup) -> decltype(auto) {
    if constexpr (std::same_as<std::remove_cvref_t<decltype(Arg)>, std::size_t>) {
        // 入参是索引,走std::get的索引重载
        return std::get<Arg>(std::forward<Tup>(tup));
    } else {
        // 入参是包装后的类型,走std::get的类型重载
        return std::get<typename decltype(Arg)::type>(std::forward<Tup>(tup));
    }
};
}

调用示例:

std::tuple<int, std::string> sample_tup{10, "hello"};
// 索引版本可直接用
auto get_idx0 = myns::get<0>;
get_idx0(sample_tup); // 返回10
// 类型版本用t<>包装后使用
auto get_int = myns::get<myns::t<int>>;
get_int(sample_tup); // 返回10

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:06:01