这在 std::tuple; 中是如何工作的?元素“有”成员?

问题描述 投票:0回答:1

我最近在网上看到这个例子:

typedef std::tuple<
    CInput,
    CAnimation,
    CTransform
> ComponentTuple;

class Entity
{
    ...
    ComponentTuple m_components;

public:
    ...

    // component management
    template <typename T> bool has_component() const { return get_component<T>().has; }
    template <typename T, typename... TArgs> T& add_component(TArgs&&... mArgs)
    {
        auto& component = get_component<T>();
        component = T(std::forward<TArgs>(mArgs)...);
        component.has = true;
        return component;
    }
    template <typename T> T& get_component() { return std::get<T>(m_components); }
    template <typename T> const T& get_component() const { return std::get<T>(m_components); }
    template <typename T> void remove_component() { get_component<T>() = T(); }
};

我已经研究了这段代码几个小时,但我无法弄清楚模板成员 has_component 和 add_component 是如何工作的 - 特别是与“has”成员一起工作。这是从哪里来的?在我能看到的任何地方,它都没有记录在标准中。然而,不知何故,“has”成员在 add_component 中设置为 true,并且可在 has_component 中进行检查。

显然,这里的目标是使用 has 来确定元组条目是否是默认构造的。

c++ stl tuples
1个回答
0
投票

在此提供一些结束。用户 @user17732522 提供了我需要弄清楚发生了什么的线索,以及使用 std::optional:

更好实现的建议
#include <tuple>
#include <optional>

typedef std::tuple<
    std::optional<CInput>,
    std::optional<CAnimation>
> ComponentTuple;

class Entity
{
    ...
public:
    ...

    // component management
    template <typename T> bool has_component() const { return std::get<std::optional<T>>(m_components).has_value(); }
    template <typename T, typename... TArgs> T& add_component(TArgs&&... mArgs)
    {
        std::optional<T>& opt_comp = std::get<std::optional<T>>(m_components);
        opt_comp = std::make_optional(T(std::forward<TArgs>(mArgs)...));
        return opt_comp.value();
    }
    template <typename T> T& get_component() { return std::get<std::optional<T>>(m_components).value(); }
    template <typename T> const T& get_component() const { return std::get<std::optional<T>>(m_components).value(); }
    template <typename T> void remove_component() { std::get<std::optional<T>>(m_components).reset(); }
};

通过此实现,对元组可以管理的类型绝对没有任何限制,但每个类型必须是唯一的,以便成员可以按类型而不是索引查找元素。

代码可以这样写:

    auto& anim = player->add_component<CAnimation>(...);
    std::cout << "added: " << anim << std::endl;
    std::cout << "player " << (player->has_component<CAnimation>() ? "has" : "does not have") << " the CAnimation component." << std::endl;
    player->remove_component<CAnimation>();
    std::cout << "removed" << std::endl;
    std::cout << "player " << (player->has_component<CAnimation>() ? "has" : "does not have") << " the CAnimation component." << std::endl;

非常感谢那些回复的人。

© www.soinside.com 2019 - 2024. All rights reserved.