缩写相似的数据成员
Abbreviating similar data members
下面的代码说明了这个问题:
struct Data {
int numFriends, numAcquaintances, numDates;
// etc...
};
enum Country {USA, Canada, China}; // etc...
enum Personality {Serious, Lazy, Funny}; // etc...
enum Height {SuperShort, Short, Medium, Tall, SuperTall};
class Religion {};
class Person {
std::map<Country, Data> countryStats;
std::map<Personality, Data> personalityStats;
std::map<Religion*, Data> religionStats;
std::map<Height, Data> heightStats; // And suppose there are 20 such similar data members
// The problem:
void insertNumFriends (Country country, int num) {countryStats[country].numFriends = num;}
void insertNumFriends (Personality personality, int num) {personalityStats[personality].numFriends = num;}
void insertNumFriends (Religion* religion, int num) {religionStats[religion].numFriends = num;}
// and tons of other necessary methods (how to capture all of these using templates?);
这是我想出的(不完整的)解决方案,即使注释掉的行是编译的,它仍然不是一个好方法,因为所有的if语句(事实上,它只是和原来的方法一样长):
#include <iostream>
#include <map>
#include <typeinfo>
#include <typeindex>
struct Data {
int numFriends, numAcquaintances, numDates;
// etc...
};
enum Country {USA, Canada, China, France}; // etc...
enum Personality {Serious, Lazy, Funny}; // etc...
enum Height {SuperShort, Short, Medium, Tall, SuperTall};
class Religion {};
template <typename T> // new struct here
struct Stats {
std::map<T, Data> map;
};
class Person {
Stats<Country> countryStats;
Stats<Personality> personalityStats;
Stats<Religion*> religionStats;
Stats<Height> heightStats; // And suppose there are 20 such similar data members
// template <typename T> static std::map<std::type_index, Stats<T>> statsMap; // illegal
public:
template <typename T>
void insertNumFriends (const T& t, int num) {
if (typeid(T) == typeid(Country)) {countryStats.map[t].numFriends = num;}
// lines below will not compile, and it's a terrible method anyway:
// else if (typeid(T) == typeid(Personality)) personalityStats.map[t].numFriends = num;
// else if (typeid(T) == typeid(Religion)) religionStats.map[t].numFriends = num;
// else if (typeid(T) == typeid(Height)) heightStats.map[t].numFriends = num;
}
void showAllStats() const { // for testing only
for (int COUNTRY = USA; COUNTRY <= France; COUNTRY++) {
auto it = countryStats.map.find(static_cast<Country>(COUNTRY));
if (it != countryStats.map.end())
std::cout << "Country " << COUNTRY << ": " << it->second.numFriends << " friends" << std::endl;
}
// etc...
}
};
int main() {
Person bob;
bob.insertNumFriends (USA, 5);
bob.insertNumFriends (France, 2);
// bob.insertNumFriends (Funny, 3); // won't compile because insertNumFriends<T> is not complete
bob.showAllStats(); // USA: 5 friends, France: 2 friends
}
什么是更好的(有效的解决方案)?无循环访问者模式或类似的东西?注意:Person有数据成员,如姓名,年龄,国家,外国人,身高等…Too和确实代表一个人,而不仅仅是容器的接口(上面的容器数据成员是这个人的"记录")。
一个可能的解决方案:模拟c++ 1y变量模板
定义一个保存数据的函数,在本例中为map:
template<typename T>
std::map<T,Data>& map()
{
static std::map<T,Data> _map;
return _map;
}
现在只创建一个泛型插入函数:
template<typename T>
void insert_data( const T& key , const Data& data )
{
map<T>()[key] = data;
}
是的,Manu的解决方案是如此简短和优雅!只是漂亮!下面是我使用他的方法编写的代码,最后我发现需要使用指向数据成员的晦涩的指针:
#include <iostream>
#include <map>
struct Data {
int numFriends, numAcquaintances, numDates;
};
enum Country {USA, Canada, France};
class Religion {} *Islam = new Religion;
class Person {
private:
template<typename T>
std::map<T, Data>& dataMap() {static std::map<T, Data> map; return map;} public:
template<typename T>
void insert (const T& key, int Data::*dataPtr, int num) {
dataMap<T>()[key].*dataPtr += num; // pointer to data members finally useful!
}
void print() { // for testing the results only
std::cout << "Number of American friends: " << dataMap<Country>()[USA].numFriends << std::endl;
std::cout << "Number of Islamic acquantances: " << dataMap<Religion*>()[Islam].numAcquaintances << std::endl;
}
};
int main() {
Person bob;
bob.insert (USA, &Data::numFriends, 10);
bob.insert (Islam, &Data::numAcquaintances, 20);
bob.print(); // USA friends = 10, Islamic acquaintances = 20
}
相关文章:
- 用于访问容器<T>数据成员的正确 API
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 数据成员SFINAE的C++17测试:gcc vs clang
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 静态数据成员模板专用化的实例化点在哪里
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 使用指针访问数组中的对象数据成员
- 友元函数无法访问私有数据成员 (c++)
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 将私有数据成员添加到野牛生成的类中
- 输入数据成员未按要求工作
- 二维矢量数据成员
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 调用在 HXX 文件中声明的静态数据成员
- 是否可以根据其数据成员的类型确定类型的大小
- 访问数据成员(本身是对象)的数据成员,就好像它们是类成员一样
- 使公共数据成员在C++中无法访问
- 缩写相似的数据成员