我正在阅读此Q / A here,因为我的问题相似但不同,我想知道如何执行以下操作:
假设我有一个名为Storage
的基本非模板非继承类。
class Storage {};
我希望这个类有一个单独的容器(无序的multimap)是我倾向于...这将保持std::string
为变量类型T的名称id。类本身不会是模板。但是,添加元素的成员函数将是。要添加的成员函数可能如下所示:
template<T>
void addElement( const std::string& name, T& t );
然后,此函数将填充无序多图。但是每次调用此函数时,每种类型都可能不同。所以我的地图看起来像是:
"Hotdogs", 8 // here 8 is int
"Price", 4.85f // here 4.8f is float.
如何使用模板,可变参数,甚至元组,任何或变体来声明这样一个无序的多图...如果没有类本身就是模板?我不想使用除标准之外的boost或其他库。
我试过这样的事情:
class Storage {
private:
template<class T>
typedef std::unorderd_multimap<std::string, T> DataTypes;
template<class... T>
typedef std::unordered_multimap<std::vector<std::string>, std::tuple<T...>> DataTypes;
};
但是我似乎无法使typedef正确,因此我可以像这样声明它们:
{
DataTypes mDataTypes;
}
答案 0 :(得分:1)
您标记了C ++ 17,因此您可以使用std::any
(或std::variant
如果T
类型可以是有限且已知的类型集。)。
存储值很简单。
#include <any>
#include <unordered_map>
class Storage
{
private:
using DataTypes = std::unordered_multimap<std::string, std::any>;
DataTypes mDataTypes;
public:
template <typename T>
void addElement (std::string const & name, T && t)
{ mDataTypes.emplace(name, std::forward<T>(t)); }
};
int main()
{
Storage s;
s.addElement("Hotdogs", 8);
s.addElement("Price", 4.85f);
// but how extract the values ?
}
但问题是,现在你有一个带有&#34; Hotdogs&#34;的元素。和&#34;价格&#34;地图中的键,但您没有关于值类型的信息。
因此,您必须以某种方式保存有关该值类型的信息(将std::pair
中的值转换为具有某种id类型和std::any
?)以提取它你需要它。
答案 1 :(得分:0)
我已经按照这些方针做了一些事情,实际的解决方案非常适合你的问题。
话虽如此,我在矢量上做这个,但原理也适用于地图。
如果您没有构建API,因此知道所涉及的所有类,您可以使用std::variant
这样的内容:
#include <variant>
#include <vector>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
int main() {
auto storage = std::vector<storage_t>{};
storage.push_back(ex1{});
storage.push_back(ex2{});
auto op = unspecific_operation{};
for(const auto& content : storage) {
std::visit(op, content);
}
return 0;
}
将输出:
got ex1
got ex2
如果我没记错的话,使用std::any
将启用RTTI,这可能会非常昂贵;可能是错的。
如果你提供更多关于你真正想做什么的细节,我可以给你一个更具体的解决方案。
有关无序地图的示例:
#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
class Storage {
private:
using map_t = std::unordered_multimap<std::string, storage_t>;
map_t data;
public:
Storage() : data{map_t{}}
{}
void addElement(std::string name, storage_t elem) {
data.insert(std::make_pair(name, elem));
}
void doSomething() {
auto op = unspecific_operation{};
for(const auto& content : data) {
std::visit(op, content.second);
}
}
};
int main() {
auto storage = Storage{};
storage.addElement("elem1", ex1{});
storage.addElement("elem2", ex2{});
storage.addElement("elem3", ex1{});
storage.doSomething();
return 0;
}