【问题标题】:Could this templated syntax be improved?这种模板化的语法可以改进吗?
【发布时间】:2014-08-18 11:40:04
【问题描述】:

我有这个模板方法:

template <class SomeLhs, class SomeRhs, 
          ResultType (SomeLhs::*callback)(SomeRhs&)>
void Add() {
  struct Local {
    static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) {
      return (static_cast<SomeLhs&>(lhs).*callback)(static_cast<SomeRhs&>(rhs));
    }
  };
  _back_end.template Add<SomeLhs,SomeRhs>(&Local::Trampoline);
}

目前我这样称呼它:

tracker.Add<Quad, Multi, &Quad::track>();
tracker.Add<Quad, Singl, &Quad::track>();
tracker.Add<Sext, Multi, &Sext::track>();
...

它工作正常,但我不想重复两次类名称SomeLhs。有没有办法避免这种情况?

对于可能已经认识它的人:是的,这与 Alexandrescu 的 BasicFastDispatcher 有关,特别是我正在编写一个与成员函数一起操作的前端。

【问题讨论】:

  • 我认为不一定总是“跟踪”功能!?您如何在 Add 中使用回调?
  • @WernerHenze 原则上它可能是另一个功能,我想保留这种可能性。 Add() 与 Alexandrescu 的几乎相同(现代 C++ 设计的第 244 页),只是有一些奇怪的语法来操作成员函数(我在问题中添加了它)。

标签: c++ templates c++11 methods


【解决方案1】:

我认为它不能特别改进,这很不幸,因为我很想找到一种方法来做到这一点。

模板类型推导仅适用于函数模板参数,您需要在编译时传入非类型成员函数指针,以便将其视为名称而不是可变数量。这意味着必须指定所有参数。

即你可以这样做:

template <class SomeLhs, class SomeRhs>
void Add(ResultType (SomeLhs::*callback)(SomeRhs&)) {
  ...
}
// nice syntax:
tracker.Add(&Sext::track);
// But ugly for overloaded functions, a cast is needed.
// p.s. not sure this is exactly the right syntax without compiling it.
tracker.Add((ResultType (Quad::*)(Multi&) &Quad::track);

但是你有一个实际的指针,随后不能用作模板参数。

我认为你唯一能做的就是使用宏,尽管它是否真的改进了这里的语法是有争议的。我会说这可能会增加不必要的混淆程度。

例如

#define TMFN_ARGS(C, M, P1) C, P1, &C::M
tracker.Add<TMFN_ARGS(Quad, track, Multi)>();

编辑:

但是,如果函数的名称是 Always 'track',您可以执行以下操作:

template <typename C, typename P1>
void AddTrack() {
   Add<C, P1, &C::track>();
}
tracker.AddTrack<Quad, Multi>();

【讨论】:

  • +1 用于宏解决方案(我倾向于忘记它们存在!)和AddTrack():我不打算拥有一堆不同的功能,所以我可以轻松地去用那个。
  • 您仍然可以在任何其他情况下使用更详细的“添加”功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-29
相关资源
最近更新 更多