Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于成员的集合模板函数_C++_Templates_C++03 - Fatal编程技术网

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
值的csv
getCsvB
为所有
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和相应的选择器函数。谢谢。将函数指针传递为