我应该如何在任何容器中存储模板化函数?

时间:2018-11-29 21:48:29

标签: c++ class templates

我有一个模板化的Prob类,可以用来组织来自不同问题集的各种编程问题。模板是问题编号。我该如何将不同的Prob对象存储在矢量或地图中?

这是类声明:

template<int ProbNum>
class Prob 
{
    std::string 
    text(std::ostream& out) 
    {
        out << "Prob" << ((ProbNum < 10) ? "0" : "") << ProbNum << ": "; 
    }

    void solve(std::ostream& out);
};

换句话说,如果我想为某个问题集的问题1声明一个对象,我会这样做

Prob<1> p1;

,然后将其存储在地图或向量中以备后用,以便用户可以在运行时对其进行调用(因为您无法将运行时参数传递给模板)。

编辑:我想将此类用作其他Prob类的抽象类。

Edit2:添加了更多代码以供澄清。

Edit3: 上半部分是Prob1.hpp

下半部分是我要如何使用它的驱动程序文件。

#include <iostream>

#include "Prob.hpp"

template<>
void
Prob<1>::solve(std::ostream& out)
{
    out << "solution to prob1";
}

/***************************************************/

#include <iostream>
#include <cstdlib>

#include "Prob.hpp"

// Finished Problems
#include "Prob1.hpp"

int
main(int argc, char* argv[])
{
    Prob<1> p;
    p.solve(std::cout);
}

1 个答案:

答案 0 :(得分:0)

模板类的每个实例构成一个不同的类型。因此,std::vector之类的容器无法容纳Prob<ProbNum>的不同值的ProbNum。 如果在编译时知道所需的Prob<ProbNum>实例的数量以及模板参数int ProbNum的相应值,则可以将所有内容存储到tuple中。例如:

auto mycollection = std::make_tuple(Prob<1>(), Prob<2>());

更通用的解决方案是为Prob定义一个抽象基类。然后,如果您定义了指向基类的指针向量,则可以设法存储Prob<ProbNum>对象的向量,其值具有int ProbNum的不均匀。为此,您必须在基类中提供接口,即要通过基类的Prob<ProbNum>访问的vector的每个成员都必须为virtual并且已经在基类中声明。

考虑以下示例:

#include <iostream>
#include <memory>
#include <vector>

struct base {
  virtual void print() const = 0;
  virtual ~base() = default;
};

template <int i>
struct derived : public base
{
  virtual void print() const { std::cout << i << std::endl; }
};

int main()
{
  std::vector<std::unique_ptr<base>> vec;
  vec.emplace_back(new derived<1>());
  vec.emplace_back(new derived<3>());
  vec.emplace_back(new derived<5>());
  for (auto& el : vec)
    el->print();

  return 0;  
}

变量vec本质上是指向derived<i>类型的对象的指针的向量,其值i不均匀。由于base::print()是虚拟的,因此它可以正确解析为derived<i>类的相应方法。 请注意,我使用了smart pointer来避免内存泄漏。

此外,声明virtualbase的析构函数很重要,请参见讨论Why should I declare a virtual destructor for an abstract class in C++?