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

C++20如何通过std::type_identity标记从std::tuple中按类型取值

实现方案

该需求完全可以通过C++20特性实现,核心思路是编译期匹配tuple中继承了对应std::type_identity标记的元素类型,直接返回对应元素的引用即可。

实现代码

你只需要替换GetThing函数的实现即可,完整可运行代码如下:

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

template<typename...Types>
class Things
{
public:
    template<typename T>
    auto& GetThing() {
        return std::apply([](auto&... args) -> auto& {
            // 编译期统计匹配的类型数量
            constexpr std::size_t match_count = (... + 
                (std::is_base_of_v<std::type_identity<T>, std::remove_cvref_t<decltype(args)>> ? 1 : 0));
            static_assert(match_count == 1, 
                "匹配失败:不存在目标标记类型,或存在多个同标记的类型导致歧义");

            // 找到匹配的元素返回引用
            auto* matched = (... + [&](){
                using U = std::remove_cvref_t<decltype(args)>;
                if constexpr (std::is_base_of_v<std::type_identity<T>, U>) {
                    return &args;
                } else {
                    return static_cast<U*>(nullptr);
                }
            }());
            return *matched;
        }, things);
    }

private:
    std::tuple<Types...> things{};
};

struct FooType {};

struct FooA : std::type_identity<FooType> {};
struct FooB : std::type_identity<FooType> {};
struct Bar {};

int main()
{
    {
        Things<FooA, Bar> things1;
        auto& foo = things1.GetThing<FooType>();
        static_assert(std::is_same_v<decltype(foo), FooA&>);
    }
        
    {
        Things<FooB, Bar> things2;
        auto& foo = things2.GetThing<FooType>();
        static_assert(std::is_same_v<decltype(foo), FooB&>);
    }
}

实现说明

  • 利用C++20的泛型lambda和折叠表达式,编译期完成所有类型检查和匹配,没有运行时开销
  • 内置静态断言检查匹配结果,当不存在匹配类型或者存在多个同标记的类型时,会直接抛出编译错误提示,避免运行时问题
  • 完全兼容你给出的测试用例,两个static_assert都能正常通过

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 19:54:04