首页 > 解决方案 > 基于 C++ 模板的 get()

问题描述

我有一堂课,里面有几个“相似”类型的成员,比如:

class Container {

    C1 c1;
    C2 c2;
    C3 c3;
    ....

    template <typename T>
    const T& get() {
        ????
    }
};

该类有一个模板化方法get<T>(),可用于获取对类型成员的引用T- 即

Container cont;

const auto& c1 = cont.get<C1>();

访问该c1成员。的当前实现get<T>()基于类中表示的所有类型的特化Container。有没有一种优雅的方法可以在不手动实现专业化的情况下实现相同的目标?

标签: c++templates

解决方案


您可以使用constexpr指向数据成员的指针元组来解决std::get. 这在不改变现有实现的情况下实现了行为,并提供了一个安全且简单的修改点。

#include <tuple>

struct C1 {};
struct C2 {};

class Container 
{
public:
    template <typename T>
    const T& get() 
    {
        constexpr auto ptr_tuple = std::make_tuple(
            &Container::c1,
            &Container::c2);

        // T Container::* is a pointer to a data member of `Container` which has the type `T`
        auto member_ptr = std::get<T Container::*>(ptr_tuple);
        return this->*member_ptr;
    }

private:
    C1 c1;
    C2 c2;
    
};

int main()
{
    Container c;
    const C1 & foo = c.get<C1>();
    const C2 & bar = c.get<C2>();
}

如果您需要经常根据模板参数选择成员,您可以将元组移出get()并使其成为constexpr static数据成员:

class Container 
{
public:
    template <typename T>
    const T& get() 
    {
        auto member_ptr = std::get<T Container::*>(ptr_tuple);
        return this->*member_ptr;
    }

private:
    C1 c1;
    C2 c2;
    
    static constexpr auto ptr_tuple = std::make_tuple(
        &Container::c1,
        &Container::c2);   
};

推荐阅读