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

如何获取C++模板参数成员变量type_id的列表?

Alright, let's tackle this problem step by step. We need to implement two key parts for the processor template class: the get_type_ids function that collects all the type_id values from the template parameters, and a type-checking mechanism to ensure only valid base_type derivatives are passed to process.

1. Implementing get_type_ids

This is straightforward with C++11's parameter pack expansion. We can directly initialize a std::vector<uint64_t> using the type_id static members of each template argument:

std::vector<uint64_t> get_type_ids() const {
    return {Args::type_id...};
}

The ... expands the template parameter pack Args into a comma-separated list of Args::type_id values, which the vector's initializer list constructor uses to populate the container.

2. Adding Type-Checking for process

To make the type check efficient and reusable, we'll store the allowed type_id values in an std::unordered_set (for O(1) average lookup time) as a private member of the processor class. Then, we'll add helper functions to validate each argument before processing.

Here's the complete, working implementation:

#include <iostream>
#include <vector>
#include <unordered_set>
#include <type_traits>

struct base_type {
    static const uint64_t type_id = 0x0;
};
struct A : public base_type {
    static const uint64_t type_id = 0xA;
};
struct B : public base_type {
    static const uint64_t type_id = 0xB;
};
struct C : public base_type {
    static const uint64_t type_id = 0xC;
};

template <class... Args>
struct processor {
private:
    // Store allowed type IDs for fast lookup
    const std::unordered_set<uint64_t> allowed_types_{Args::type_id...};

    // Helper to check a single object's type ID
    bool is_type_allowed(const base_type& obj) const {
        // Use count() for pre-C++20 compatibility; contains() works in C++20+
        return allowed_types_.count(obj.type_id) > 0;
    }

    // C++11-compatible recursive check for all arguments
    bool check_all() const { return true; }
    template <class First, class... Rest>
    bool check_all(const First& first, const Rest&... rest) const {
        static_assert(std::is_base_of<base_type, typename std::decay<First>::type>::value,
                      "Argument must derive from base_type");
        return is_type_allowed(first) && check_all(rest...);
    }

public:
    std::vector<uint64_t> get_type_ids() const {
        return {Args::type_id...};
    }

    void process(const base_type&... args) const {
        // Validate all arguments
        if (!check_all(args...)) {
            std::cout << "One of the arguments to process was not the correct type" << std::endl;
            return;
        }

        // Safe to process arguments here - add your custom logic below
        std::cout << "Processing valid arguments:" << std::endl;
        ((std::cout << "  Type ID: 0x" << std::hex << args.type_id << std::endl), ...);
    }
};

int main() {
    processor<A, B> my_processor;
    B b;
    C c;

    // This will trigger the error message since C's type_id isn't allowed
    my_processor.process(b, c);

    // Uncomment to test valid arguments
    // A a;
    // my_processor.process(a, b);
}

Key Details:

  • Efficient Lookup: Using std::unordered_set ensures that checking each type ID is fast, even with many template parameters.
  • Compile-Time Safety: The static_assert in check_all ensures that only base_type derivatives are passed to process, catching invalid types at compile time instead of runtime.
  • C++11 Compatibility: The recursive check_all function works with C11. If you're using C17 or later, you can simplify this with a fold expression:
    bool all_allowed = (is_type_allowed(args) && ...);
    
  • Flexible Error Handling: We've kept the error message matching your example, but you could also throw an exception for stricter error handling if needed.

When you run this code, it will output the expected error message because C's type_id isn't in the allowed set for processor<A, B>.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 08:57:55