首页 > 解决方案 > 具有更改返回类型的可变参数模板参数列表

问题描述

我正在尝试使用不断变化的返回类型制作模板化可变参数。如果参数的数量是 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<A>(var);VS 说他不能从 void 转换为 A*,这说明 decltype(auto) 以某种方式变为 void

并且在return AddComp <Args>(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 中遇到的错误 VSError

标签: c++templatesc++14variadic

解决方案


直截了当

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

似乎工作得很好。Clang 演示, MSVC 演示


Here's a solution that works with 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


推荐阅读