4

我有一个带有模板化成员函数的类:

class Person
{
  template <typename TItem>
  void DoSomething(TItem item)
  {
    item.Action();
  } 
};

这允许我通过一个 Action 成员函数传递任何项目,并且该人将对该项目执行该操作。所以我可以这样做:

Person person;
BaseballBat bat;
person.DoSomething(bat);

这种结构允许我使用任何类型的对象调用函数。但是,如果我想存储任何类型的对象,我必须模板类:

template <TItem>
class Person
{
public:
  void DoSomething()
  {
    this->Item.Action();
  }

  void SetItem(TItem item)
  {
    this->Item = item;
  }
private:
  TItem Item;
};

Person<BaseballBat> person;
BaseballBat bat;
person.SetItem(&bat);
person.DoSomething();

这很烦人,因为我必须重新实例化 Person 类来更改对象的类型。

或者,我可以从父类派生项目:

class Person
{
public:
  void DoSomething()
  {
    this->Item.Action();
  }

  void SetItem(TItem* item)
  {
    this->Item = item;
  }

private:
  ParentItem* Item;
};

class ParentItem{};

class BaseballBat : public ParentItem
{}

Person person;
BaseballBat bat;
person.SetItem(&bat);
person.DoSomething();

这很烦人,因为我必须维护所有项目的继承结构(这似乎非常“非 GP”)。

当我有多层“包含对象的对象”时,问题就真的出现了——也就是说,我必须将函数模板参数从一个非常“顶级”的调用“传递”到包含的类:

class BaseballBat
{
  void DoAction();
};

class Child
{
  template <typename TItem>
  void DoAction(TItem item)
  {
    item.DoAction();
  }
};

class Person
{
  Child child;

  // This is annoying to have to pass the item to the person, who then has to pass it to the child. I'd rather "give" the child an Item, then just be able to call child.DoAction(), where the Person doesn't know anything about the item.
  template <typename TItem>
  void PlayWithChild(TItem item)
  {
    child.DoAction(item);
  }
}

任何人都可以评论如何正确混合函数模板和将对象存储为成员数据的这两种想法吗?(以上只是试图证明的俗气的例子——如果它们没有意义或者你有更好的例子,我会全神贯注:))。

--------- 编辑 --------- 也许一个更好的例子是我的真实案例的简化。我有一个具有成员函数的类 Matcher:

template<typename TDistanceFunctor, typename TPropagationFunctor>
void Matcher::Compute(TDistanceFunctor distanceFunctor, TPropagationFunctor propagationFunctor);

然后我有另一个类 ImageAlgorithm,它使用了 Matcher:

template<typename TMatcher>
void ImageAlgorithm::Compute(TMatcher matcher)
{
  matcher.Compute(...); // How do I get the DistanceFunctor and the PropagationFunctor here?
}

我想这样称呼这些东西:

Matcher myMatcher;
.... Setup matcher (how?) ...
ImageAlgorithm algorithm;
algorithm.Compute(myMatcher);

我不知道如何通过 ImageAlgorithm 对象“通过”DistanceFunctor 和 PropagationFunctor,以便它可以到达 ImageAlgorithm::Compute 调用中的 Matcher 对象。当然,我可以在 TDistanceFunctor 上模板 Matcher 并将 TDistanceFunctor 存储为成员变量,但后来我无法将匹配器使用的距离仿函数更改为不同类型的距离仿函数。

4

1 回答 1

1

您可以尝试使用boost::any来保存您的类型变体成员。

从概述:

boost::any 类 (...) 支持复制任何值类型并严格根据其类型安全检查提取该值。

编辑

你是对的,使用 boost any 调用存储的函子是有问题的。所以我建议另一种解决方案:使用 std::function (或 boost::function)来包装你的仿函数。这样,Matcher 可以保存相关语法的函数对象(例如,没有参数),并且不需要在仿函数类型上进行模板化。

函数对象已经为您完成了 OO(至少在某种意义上)和 GP 之间的组合。

于 2012-08-11T20:44:48.997 回答