C++:我可以在模板参数包中强制执行至少 1 个参数吗

标签 c++ variadic-templates template-meta-programming

这更多是我正在考虑的设计限制。这段代码针对的是虚幻引擎,以防您对语法感到疑惑——但这应该与问题无关。

此模板代码仅采用用户想要实例化的对象类型 - 然后创建一个拥有容器对象并调用所有者的 add 方法。 (业主负责实际构建逻辑)

template<typename T>
void UEntityFactory::Create_Impl(AEntityObject* owner)
{
    static_assert( TPointerIsConvertibleFromTo<T, UEntity>::Value, "[UEntityFactory] ERROR: Attempting to create a non-entity type");
    owner->AddEntity<T>();
}

// Templated create accepting variadic arguments; it first creates the housing entity object
// and then recursively generates code for each argument.
template <typename T, typename...Args>
AEntityObject* UEntityFactory::Create()
{
    // Create the owning EntityObject
    AEntityObject* obj = NewObject<AEntityObject>(this);
    Create_Impl<T>(obj);

    // Recursively call Create_Impl for Args
    Create_Impl<Args...>(obj);
    return obj;
}

根据我从模板参数包中了解到的情况,可变参数(在我的例子中是...Args)是可选的。使用两个类型名称而不是一个参数包的基本原理是确保用户至少传递一个模板参数。

我想限制创建过程以确保始终创建有效的对象。但是如果我调用如下一行,上面的代码将无法编译:

AEntityObject* obj = factory.Create<EntityA>();

我认为我设置模板声明的方式需要另一个参数。 错误如下:

  • ' UEntityFactory::Create_Impl ': 未找到匹配的重载函数
  • 注意:请参阅函数模板实例化引用“AEntityObject *UEntityFactory::Create<UDebugEntityA,>(void)” ' 正在编译
  • ' void UEntityFactory::Create_Impl(AEntityObject *) ': 无法推断出 'T' 的模板参数

这是其中一个错误,我知道它为什么会发生,但我无法说清楚。果然,如果我将 Create 函数的声明更改为以下内容,它可以正常编译:

template <typename...Args>
AEntityObject* UEntityFactory::Create()
{
    AEntityObject* obj = NewObject<AEntityObject>(this);

    // Recursively call Create_Impl for Args
    Create_Impl<Args...>(obj);
    return obj;
}

然而这意味着,用户现在可以写

AEntityObject* obj = factory.Create<>();

这是我想避免的。有没有一种优雅的方法来强制至少一个模板参数,以及一个可选的 set 可变参数?我不能重载 Create 方法,因为那样会产生不明确的调用。

编辑:我搞砸了,我错误地认为我的参数一开始就被正确展开了——感谢 Jarod42 的纠正。

最佳答案

好吧,您可以只添加一个 static_assert() 来进行检查并发出一个更有意义的编译时错误:

template <typename...Args>
AEntityObject* UEntityFactory::Create()
{
    static_assert(sizeof...(Args) > 0, "Create() would like to have at least one object type to create...");

    AEntityObject* obj = NewObject<AEntityObject>(this);

    // Recursively call Create_Impl for Args
    Create_Impl<Args...>(obj);
    return obj;
}

关于C++:我可以在模板参数包中强制执行至少 1 个参数吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51585491/

相关文章:

C++ "expected a declaration"

c++ - 如何调试 Excel 对 COM 服务器的加载?

c++ - 在 C++ 中创建一个特征来检测闭包类型

c++ - 从 boost asio 向浏览器发送多个响应

c++ - 不推荐从字符串文字到 char* 的转换

非类型参数的 C++ 可变参数模板偏特化

C++ 11使可变参数构造函数理解初始化列表的初始化列表

javascript - 如何从标签函数调用原生 es6 模板字符串替换?

C++17:在编译时将类型映射到整数值

c++ - 仅当类有一个特定方法时如何调用?