【问题标题】:Variadic template argument list with changing return type具有更改返回类型的可变参数模板参数列表
【发布时间】:2020-11-16 03:21:39
【问题描述】:

我正在尝试使用不断变化的返回类型制作模板化可变参数。 如果参数的数量是 1,那么它应该返回一个指向唯一参数的指针,否则它应该返回一个参数指针的元组:

int var = 0;
A *ptr_A = foo<A>(var);
auto *[ptr_A, ptr_B] = foo<A, B>(var);

这是我目前的代码

template<typename T>
T* AddComp(EntityId entityID)
{
    componentPool<T>* pool = GetOrCreatePool<T>();
    return pool->Create(entityID);
}

template <typename... Args>
decltype(auto) AddComponent(EntityId entityID)
{
    if constexpr (sizeof...(Args) == 1)
    {
        return AddComp <Args>(entityID);
    }
    else
    {
        return std::tuple<decltype(AddComponent<Args>({}))... > {AddComponent<Args>(entityID)...};
    }
}

但我遇到了几个错误:

如果A *ptr_A = foo&lt;A&gt;(var); VS 说他不能从 void 转换为 A*,这说明 decltype(auto) 不知何故变成了 void

并且在return AddComp &lt;Args&gt;(entityID); VS 中说必须扩展 Args 参数包。即使 Args 是一个参数,我还需要以某种方式扩展它吗?

谢谢!

编辑:

根据要求,我提供了一个最小的示例

using EntityId = size_t;

class A
{
public:

int a;
};

class B
{
public:

int b;
};

class componentsManager
{
    
public:

template<typename T>
T* AddComp(EntityId entityID)
{
    return new T();
}

template <typename... Args>
decltype(auto) AddComponent(EntityId entityID)
{
    if constexpr (sizeof...(Args) == 1)
    {
        return AddComp <Args>(entityID);
    }
    else
    {
        return std::tuple<decltype(AddComponent<Args>({}))... > {AddComponent<Args>(entityID)...};
    }
}
    
};

componentsManager m_manager;
EntityId id;

A *ptr_A1 = m_manager.AddComponent <A>(id);
auto *[ptr_A2, ptr_B] =  m_manager.AddComponent<A, B>(id);// This will only compile in c++17 i believe, i am using c++14

编辑2:

我在 VS 2019 中遇到的错误

【问题讨论】:

  • 你需要return AddComp&lt;Args...&gt;(entityID);
  • @HolyBlackCat 是的,我之前尝试添加扩展 ...,但我收到一条错误消息“预期 >”。
  • 你能发一个minimal reproducible example吗?
  • @cigien 我添加了一个我认为有用的示例
  • 您说您使用的是 C++14,但您始终依赖于 C++17 功能,例如if constexpr。你能或不能使用 C++17 吗?在 C++17 之前,您需要两个重载。

标签: c++ templates c++14 variadic


【解决方案1】:

直截了当

if constexpr (sizeof...(Args) == 1)
{
    return AddComp<Args...>(entityID);
}

似乎工作得很好。 Clang demo, MSVC demo


这是一个适用于 C++14 的解决方案:

template <typename T>
decltype(auto) AddComponent(EntityId entityID)
{
  return AddComp<T>(entityID);
}

template <typename... Args>
decltype(auto) AddComponent(
    std::enable_if_t<(sizeof...(Args) > 1), EntityId> entityID)
{
    return std::tuple<decltype(AddComponent<Args>({}))...>{
        AddComponent<Args>(entityID)...};
}

Demo

【讨论】:

  • 完美运行。由于转发错误,IntelliSense 错误地抛出了该错误。
猜你喜欢
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
相关资源
最近更新 更多