[英]Why are template (non-static) member variables not supported in C++?
雖然靜態成員變量可以在C ++ 14中模板化,但這不起作用:
class SomeClass
{
public:
template<typename T>
T var = {};
};
int main()
{
SomeClass instance;
instance.var<int> = 50;
instance.var<double> = 0.1;
}
是什么原因導致C ++標准不支持變量成員的模板,因為它原則上應該是可能的?
實例化該類時,您不知道它將使用多少內存。 這個類是否包含int和double? 如果你寫的怎么辦?
instance.var<float> = 0.2;
instance.var<long long> = 1;
稍后在您的代碼中
這將使兩個相同類型的對象SomeClass
不同,渲染類概念,因為我們在c ++中理解它是無用的。
此外,您的代碼示例意味着var
可以在運行時更改類型,這可以使用std :: variant或std :: any來完成。
它不能在原則上還是在實踐中是可行的,因為其他的答案解釋: sizeof(SomeClass)
將是不可能的計算一般,而SomeClass
將不再有任何可預見或理智的身份,擊敗它存在的目的。
如果您只想選擇幾種類型,並且希望在運行時更改“選定”類型,那么您可能正在尋找變體 ?
#include <variant>
class SomeClass
{
public:
std::variant<int, double> var = {};
};
int main()
{
SomeClass instance;
instance.var = 50;
instance.var = 0.1;
}
(這需要C ++ 17 ,但許多年來都有一個Boost等效版本。)
它的工作原理,因為var
會,因為它需要存儲或者一個大int
或double
(加上一些家政服務),而這個大小是固定的,無論其“模式”的變種是在任何給定的時間。
如果你想接受任何類型,你可以使用std::any
,這就像毒品的變種。 開銷有點重,但如果您的要求非常輕松,那么這可以完成工作。
但是如果你想要多個變量,那就有多個變量。
c ++具有已知大小的值類型。 您可以創建的所有C ++完整類型都可以由編譯器根據該編譯單元中創建行或其以上的信息計算其大小。
為了做你想做的事情,類的實例大小隨着在任何編譯單元中使用的每個模板變量而變化,或者實例的大小隨着添加新元素而隨時間變化。
現在您可以根據類型創建新數據,但它不會在類中; 相反,您添加一個存儲數據的地圖。
using upvoid=std::unique_ptr<void, void(*)()>;
template<class T>
static upvoid make(){
return { new T, [](void*ptr){ delete static_cast<T*>(ptr); } };
}
std::map<std::type_index, upvoid> m_members;
template<class T>
T& get() {
auto it = m_members.find(typeid(T));
if (it == m_members.end()){
auto r = m_members.insert( {typeid(T), make<T>()} );
it=r.first;
}
return *it.second;
}
現在foo.get<int>()
分配一個int
如果它不在那里,如果它在那里得到它。 如果您希望能夠復制實例,則必須完成額外的工作。
這種混亂模仿你想要的東西,但它的抽象泄漏(你可以告訴它不是一個成員變量)。 它實際上不是一個模板成員變量,它只是有點像一個。
除非做這樣的事情,你要求的是不可能的。 坦率地說,作為語言的一部分,這樣做是一個壞主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.