C++ 基于成员的集合模板函数
我有以下结构C++ 基于成员的集合模板函数,c++,templates,c++03,C++,Templates,C++03,我有以下结构 struct Obj { int a; int b; }; class ObjCollection { map<int,Obj> collMap; public: string getCsvA(); string getCsvB(); }; 结构对象 { INTA; int b; }; 类对象集合 { 地图;地图; 公众: 字符串getCsvA(); 字符串getCsvB(); }; getCsvA返回collMap对象中所有a值的csv
struct Obj
{
int a;
int b;
};
class ObjCollection
{
map<int,Obj> collMap;
public:
string getCsvA();
string getCsvB();
};
结构对象
{
INTA;
int b;
};
类对象集合
{
地图;地图;
公众:
字符串getCsvA();
字符串getCsvB();
};
getCsvA
返回collMap
对象中所有a
值的csvgetCsvB
为所有b
值返回相同的值
有没有一种方法可以模板化这个函数?对我来说,它变得复杂的原因是我无法从这个类之外(即从我的客户机代码)传递我要为哪个成员生成csv的地址。有办法做到这一点吗?
注意:我不能使用C++11 这似乎需要一个函数作为
getCsv
的参数,而不是模板:
将函数声明为string getCsv(int(*selectMember)(Obj))
。此外,在getCsvA
中使用selectMember([…])
的任何地方使用selectMember([…])
现在,您可以调用getCsv
,提供返回Obj
右侧字段的方法,例如:
int selectA(Obj o)
{
return o.a;
}
这似乎需要一个函数作为
getCsv
的参数,而不是模板:
将函数声明为string getCsv(int(*selectMember)(Obj))
。此外,在getCsvA
中使用selectMember([…])
的任何地方使用selectMember([…])
现在,您可以调用getCsv
,提供返回Obj
右侧字段的方法,例如:
int selectA(Obj o)
{
return o.a;
}
虽然有点不雅观,但如果您只有两个字段,则可以合理地使用
getCsvA
和getCsvB
调用getCsv(a_或B a_或B_或B)
函数,给定enum a_或B{a,B}
,然后在迭代collMap
时在getCsv
内说int value=(a\u或b==a)?迭代器->a:迭代器->b
,然后将该值放入csv字符串中。比担心指向成员数据、函子或模板的指针更容易:当您熟悉这一级别的编程时,您就可以担心更抽象的方法(希望届时您可以使用C++11,因为lambdas非常适合这种方法)。虽然有点不雅观,如果您只有两个字段,您可以合理地使用getCsvA
和getCsvB
调用getCsv(a_或B a_或B_或B)
函数,给定枚举a_或B{a,B}
,然后在迭代collMap
时在getCsv
内说int value=(a\u或b==a)?迭代器->a:迭代器->b
,然后将该值放入csv字符串中。比担心指向成员数据、函子或模板的指针更容易:当您对这种级别的编程感到满意时,您就可以担心更抽象的方法(希望届时您可以使用C++11,因为lambdas非常适合这样做)。您拥有的代码框架看起来还不错。通常,将不需要参数化的东西参数化是个坏主意。模板是最强大的方式,但它们确实应该被同等谨慎地使用
通过添加参数,您可以为错误代码(错误的函数指针、空指针等)添加更多机会。使用函数指针或虚拟方法也会给编译器的优化带来更大的困难,因为执行的代码通常必须在运行时解析
但是,如果您使用C++11而不是C++03,那么使用a而不是裸struct
可能是有意义的,并且您将得到一个模板函数作为奖励
#include <utility>
template<typename... Ts>
class TupleCollection {
public:
template<std::size_t I>
std::string getCsv() {
for (const auto& p : collMap) {
std::string v = static_cast<std::string>(std::get<I>(p.second));
...
}
}
private:
std::map<int, std::tuple<Ts...>> collMap;
};
#包括
模板
类元组集合{
公众:
模板
std::string getCsv(){
用于(常数自动&p:collMap){
std::string v=static_cast(std::get(p.second));
...
}
}
私人:
std::map collMap;
};
然后以编译时安全的方式获取相关字段的CSV将是
tc.getCSV<0>();
tc.getCSV<1>();
tc.getCSV();
tc.getCSV();
您拥有的代码框架实际上看起来还不错。通常,将不需要参数化的东西参数化是个坏主意。模板是最强大的方式,但它们确实应该被同等谨慎地使用
通过添加参数,您可以为错误代码(错误的函数指针、空指针等)添加更多机会。使用函数指针或虚拟方法也会给编译器的优化带来更大的困难,因为执行的代码通常必须在运行时解析
但是,如果您使用C++11而不是C++03,那么使用a而不是裸struct
可能是有意义的,并且您将得到一个模板函数作为奖励
#include <utility>
template<typename... Ts>
class TupleCollection {
public:
template<std::size_t I>
std::string getCsv() {
for (const auto& p : collMap) {
std::string v = static_cast<std::string>(std::get<I>(p.second));
...
}
}
private:
std::map<int, std::tuple<Ts...>> collMap;
};
#包括
模板
类元组集合{
公众:
模板
std::string getCsv(){
用于(常数自动&p:collMap){
std::string v=static_cast(std::get(p.second));
...
}
}
私人:
std::map collMap;
};
然后以编译时安全的方式获取相关字段的CSV将是
tc.getCSV<0>();
tc.getCSV<1>();
tc.getCSV();
tc.getCSV();
这不意味着我必须在客户端代码中传递函数吗。类似于objCollection.getCsv(selectA);getCsv(selectB);这意味着我必须公开函数selectA和selectB,对吗?如果我的理解是错误的,你能给我一个如何调用函数的例子吗?你是对的。在某种程度上,你必须让客户选择使用哪个成员——当然还有其他的方式,你更喜欢什么样的“接口”?我更愿意考虑客户机创建那些“选择…”方法-客户机是否可以看到Obj
?我想有两个单独的接口,getCsvA和getCsvB。我想我可以在内部调用pass和相应的选择器函数。谢谢。将函数指针传递为