[英]How to iterate through all typenames in a class template?
我想為我的游戲設計一個基於組件的武器模板。 但是,似乎沒有辦法添加/刪除 class 成員或創建代碼?
對不起我的表達和缺乏術語,因為我沒有從部門畢業。 計算機科學或軟件工程師,我對專業人士所說的那些東西知之甚少。
這是組件代碼的樣子:
class CBaseWpnCmpt : public std::enable_shared_from_this<CBaseWpnCmpt>
{
public:
typedef std::shared_ptr<CBaseWpnCmpt> PTR;
private:
CBaseWpnCmpt() = default;
public:
CBaseWpnCmpt(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt(CBaseWpnCmpt&& s) = default;
CBaseWpnCmpt& operator=(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt& operator=(CBaseWpnCmpt&& s) = default;
virtual ~CBaseWpnCmpt() {}
protected:
CBaseWeaponInterface::PTR m_pWeapon { nullptr };
public:
template <class CComponent>
static std::shared_ptr<CComponent> Create(CBaseWeaponInterface::PTR pWeapon)
{
std::shared_ptr<CComponent> pComponent = std::make_shared<CComponent>();
pComponent->m_pWeapon = pWeapon;
return pComponent;
}
};
這就是武器主體代碼的樣子:(問題就出現了)
template < class CWeapon,
class ...CComponents
>
class CBaseWeaponTemplate : public CBaseWeaponInterface
{
public:
std::list<CBaseWpnCmpt::PTR> m_lstComponents;
public:
virtual void SecondaryAttack(void) // Example method.
{
for (auto& pComponent : m_rgpComponents)
{
pComponent->SecondaryAttack();
}
}
};
我想如何將所有這些參數包創建為模板的成員? 目前我試圖將它們登記到指針 std::list 容器中,但我根本不知道如何實現它。
換句話說,當我填寫空白時如何制作模板,如下所示:
class CAK47 : public CBaseWeaponTemplate<CAK47, CLongMagazine, CWoodenStock>
將生成:
class CAK47
{
CLongMagazine m_comp1;
CWoodenStock m_comp2;
//... other stuff
};
或者,生成這個:
class CAK47
{
CAK47() // constructor
{
for (/* somehow iterate through all typenames */)
{
CBaseWpnCmpt::PTR p = std::make_shared<typename>();
m_lstComponents.emplace_back(p);
}
}
};
從 C++11 開始的一種方法是將用於此特定武器的模板類型存儲在std::tuple
中
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments() {
return;
}
std::tuple<Attachments...> attachment_types;
};
然后使用該元組使用受保護的構造函數初始化一個共享指針向量,該構造函數采用一個元組再次訪問模板類型。
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&)
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
如果attachments
向量已經在父 class 中聲明,就像它似乎是這種情況,您也可以通過初始化父 class 中的附件來避免元組和受保護的構造函數
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments()
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
然后只在派生的 class 中調用基礎 class 的構造函數
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment>() {
return;
}
};
如果這不是您的選擇,那么您可以使用元組使用 C++17 折疊表達式遍歷所有模板 arguments:
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&) {
(attachments.push_back(std::make_shared<Attachments>()), ...);
return;
}
};
在 C++17 中,您還可以在構造函數中添加帶有折疊表達式的 static 斷言,以確保類型實際上繼承自BaseAttachment
:
static_assert((std::is_base_of_v<BaseAttachment, Attachments> && ...), "Template arguments must inherit from 'BaseAttachment'.");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.