簡體   English   中英

C ++:我可以在模板參數包中強制執行至少1個參數

[英]C++: Can I enforce at least 1 agument in a template parameter pack

這更多是我正在考慮的設計約束。 如果您想了解語法,此代碼段針對的是虛幻引擎-但這與問題無關。

該模板代碼僅采用用戶想要實例化的對象類型-然后創建一個擁有容器的對象並在所有者上調用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)是可選的。 具有兩個類型名而不是一個參數包的基本原理是確保LEAST的用戶傳遞一個模板參數。

我想限制創建過程,以確保始終創建有效的對象。 但是,如果我調用如下代碼,則上面的代碼將無法編譯:

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

我認為在設置模板聲明的方式上,它需要另一個參數。 錯誤如下:

  • ' UEntityFactory::Create_Impl ':找不到匹配的重載函數
  • 注意:請參見對正在編譯的函數模板實例化' AEntityObject *UEntityFactory::Create<UDebugEntityA,>(void) '的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<>();

這是我要避免的。 是否有一種優雅的方法來強制至少一個模板參數以及一個可選的可變參數參數集? 我無法重載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;
}
template <typename T, typename...Args>
AEntityObject* UEntityFactory::Create()
{
    // [..]

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

不是遞歸調用

因此,實際上,您似乎很難遍歷可變參數模板。

然后,您可以使用:

template <typename T, typename...Args>
AEntityObject* UEntityFactory::Create()
{
    // Create the owning EntityObject
    AEntityObject* obj = NewObject<AEntityObject>(this);
    Create_Impl<T>(obj);

    // C++17: folding expression
    (Create_Impl<Args>(obj), ...);

    return obj;
}

和之前:

template <typename T, typename...Args>
AEntityObject* UEntityFactory::Create()
{
    // Create the owning EntityObject
    AEntityObject* obj = NewObject<AEntityObject>(this);
    Create_Impl<T>(obj);

    const int dummy[] = { 0, (Create_Impl<Args>(obj), 0)...};
    static_cast<void>(dummy); // Avoid warning for unused variable

    return obj;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM