entt基本注册表::get<>()解释

huangapple go评论131阅读模式
英文:

entt basic_registry::get<>() explanation

问题

Currently using g++11.3.0, C++20.

Could anyone explain how the basic_registry's get<>() template function is able to function such that when retrieving a single component through a call like auto& comp {registry.get<A>()};, the component itself can be directly assigned to and/or accessed like a normal reference, and when retrieving multiple components through a call like registry.get<A, B, C>(), it can be unpacked via a structured binding auto& [a, b, c].

Code (from https://skypjack.github.io/entt/registry_8hpp_source.html)

template<typename... Type>
[[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) {
    if constexpr(sizeof...(Type) == 1u) {
        return (const_cast<Type &&>(std::as_const(*this).template get<Type>(entt)), ...);
    } else {
        return std::forward_as_tuple(get<Type>(entt)...);
    }
}
英文:

Currently using g++11.3.0, C++20.

Could anyone explain how the basic_registry's get&lt;&gt;() template function is able to function such that when retrieving a single component through a call like auto&amp; comp {registry.get&lt;A&gt;()};, the component itself can be directly assigned to and/or accessed like a normal reference, and when retrieving multiple components through a call like registry.get&lt;A, B, C&gt;(), it can be unpacked via a structured binding auto&amp; [a, b, c].

Code (from https://skypjack.github.io/entt/registry_8hpp_source.html)

template&lt;typename... Type&gt;
[[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) {
    if constexpr(sizeof...(Type) == 1u) {
        return (const_cast&lt;Type &amp;&gt;(std::as_const(*this).template get&lt;Type&gt;(entt)), ...);
    } else {
        return std::forward_as_tuple(get&lt;Type&gt;(entt)...);
    }
}

答案1

得分: 1

以下是代码部分的翻译:

// 以下函数模板返回一个元组:
template <typename ...T>
auto foo() {
    return std::make_tuple(T{}...);
}

// 您可以通过以下方式调用它:
auto [a, b, c] = foo<int, int, double>();

// 以下函数模板仅返回一个 'T':
template <typename T>
auto bar() { return T{}; }

// 您可以通过以下方式调用它:
auto d{bar<int>()};

// 函数只能有一个返回类型。'foo' 和 'bar' 是函数模板。函数 'foo<int, int, double>' 和 'bar<int>' 有一个返回类型。它们返回一个值。

// 以下函数模板根据模板参数的数量选择要实例化和调用的两个函数模板之一:
template <typename ...T>
auto moo() {
    if constexpr(sizeof...(T) == 1u) { return bar<T...>(); }
    else return foo<T...>();
}

// 您可以通过以下方式调用它:
auto [x, y, z] = moo<int, int, double>();

// 或者
auto w{moo<int>()};

// 请注意,当 'T...' 多于一个参数时,'bar<T...>' 会不匹配(因为 'bar' 只有一个参数)。然而,在模板上下文中,未选择的分支在编译时会被丢弃。

// 在 'sizeof...(T) == 1u' 的情况下,参数包被展开。然而,在这种情况下,展开只有一个类型(否则 'bar<T...>' 将无法编译)。它可以写成:

template <typename T, typename ...More>
auto moo() {
    if constexpr(sizeof...(More) == 0u) { return bar<T>(); }
    else return foo<T, More...>();
}

// [在线演示](https://godbolt.org/z/n6MrYqd36)

这是代码的翻译部分,不包括问题的回答。

英文:

The following function template returns a tuple:

template &lt;typename ...T&gt;
auto foo() {
    return std::make_tuple(T{}...);
}

You can call it via

auto [a, b, c] = foo&lt;int,int,double&gt;();

The following function template returns just a T:

template &lt;typename T&gt;
auto bar() { return T{};}

you can call it via

auto d{bar&lt;int&gt;()};

Functions can have only one return type. foo and bar are function templates. The functions foo&lt;int,int,double&gt; and bar&lt;int&gt; have one return type. They return one value.


The following function template selects between two function templates to be instantiated and called depending on the number of template arguments:

template &lt;typename ...T&gt;
auto moo() {
    if constexpr(sizeof...(T) == 1u) { return bar&lt;T...&gt;(); }
    else return foo&lt;T...&gt;();
}

You can call it via:

auto [x,y,z] = moo&lt;int,int,double&gt;();

Or

auto w{ moo&lt;int&gt;()};

Note that when T... is more than a single argument then bar&lt;T...&gt; would be a mismatch (because bar has only a single argument. However, with constexpr if in template context the not taken branch is discarded at compile time.


In the case of sizeof...(T) == 1u the parameter pack is expanded. However, the expansion is only a single type in this case (otherwise bar&lt;T...&gt; would not compile). It could have been written as

template &lt;typename T,typename ...More&gt;
auto moo() {
    if constexpr(sizeof...(More) == 0u) { return bar&lt;T&gt;(); }
    else return foo&lt;T,More...&gt;();
}

Live Demo


huangapple
  • 本文由 发表于 2023年2月6日 18:15:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75359953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定