函数模板参数推导

Function template parameter deduction

本文关键字:参数 函数模板      更新时间:2023-10-16

我正在使用Reactor模式编写一个小型的基于消息的c++通信框架。我遇到的问题是应用程序(用户定义的)消息的序列化。为了防止API产生冗余信息,我对序列化函数做了一个假设。有一个Archive类保存消息的序列化形式,但它是模板,因此用户可以选择其二进制形式。假设每个消息只有一个可用的序列化函数(已定义),因此可以从函数签名中清楚地推导出二进制类型的类型推断。让我们看看代码:

template <typename T> struct Archive {
  T t;
};  // struct Archive
template <typename Message, typename T>
void serialize(const Message& msg, Archive<T>* const ar);
struct Signal {
  void* payload;
};
template <typename T> struct Wrapper {
  Signal* pack() {
    Signal* s = new Signal;
    archive(&serialize, &s->payload);
    return s;
  }
  template <typename P>
  void archive(void(*f)(const T&, Archive<P>* const), void** payload) {
    Archive<P> ar;
    f(t, &ar);
    P* p = new P;
    *p = ar.t;
    *payload = p;
  }
  T t;
};
struct TestMsg {
  int i;
};
template <>
void serialize(const TestMsg& msg, Archive<int>* const ar) {
  ar->t = msg.i;
}
int main() {
  Wrapper<TestMsg> msg;
  msg.pack();
  return 0;
}

编译器声明它不能推断p类型。有没有其他的方法(没有特征)来帮助编译器这样的演绎?

敬礼,格拉詹

编辑(14-05-2013 15:42):根据评论中的要求,我附上了性状解决方案:

/****** Library part *******/
template <typename T> struct Archive {
  T t;
};  // struct Archive
template <typename T> struct MessageTrait {};
template <typename Message, typename T>
void serialize(const Message& msg, Archive<T>* const ar);
struct Signal {
  void* payload;
};
template <typename T> struct Wrapper {
  Signal* pack() {
    typedef Archive<typename MessageTrait<T>::ArchType> ArchiveType;
    Signal* s = new Signal;
    ArchiveType ar;
    serialize(t, &ar);
    return s;
  }
  T t;
};
/****** Application part ******/
struct TestMsg {
  int i;
};
template<> struct MessageTrait<TestMsg> {
  typedef int ArchType;
};
template <>
void serialize(const TestMsg& msg, Archive<int>* const ar) {
  ar->t = msg.i;
}
int main() {
  Wrapper<TestMsg> msg;
  msg.pack();
  return 0;
}
template <typename Message, typename T>
void serialize(const Message& msg, Archive<T>* const ar);
template <typenane T>
Signal* Wrapper<T>::pack() {
    Signal* s = new Signal;
    archive(&serialize, &s->payload);
    return s;
}

在上面的代码中,serialize是模板的名称,用来代替函数,它代表了模板的所有可能的专门化(即模板参数的每一个可能的替换)所导致的重载的完整集合。同时,archive是一个模板,它可以从子集中获取任何函数,只要满足最小的限制,即第二个参数是Archive模板的实例化。

这里的问题不是模板不能推导出参数,而是有无限的类型符合要求,你的问题太开放了。这就带来了下一个问题,所有的东西都需要是模板吗?

一般来说,专门化函数模板是一个坏主意,serialize模板真的是一个过载吗?你能否将问题的通用性简化到可演绎或不可演绎只有一个或两个候选者?我有一种感觉,你把自己开放给了太多你可能需要或不需要的自由,然后被任何都可以匹配的事实所束缚。