C++重载运算符,具有从模板的多个继承

C++ overloading operator with multiple inheritance from templates

本文关键字:继承 运算符 重载 C++      更新时间:2023-10-16

我有一个层次结构,它代表HTTP客户端的某些部分,看起来像这样:

typedef list<pair<string, string> > KeyVal;
struct Header { string name; string value; ...};
struct Param { string name; string value; ...};
/* Something that contains headers */
template<typename T> class WithHeaders {
  KeyVal headers;
public:
  virtual T &operator <<(const Header &h) {
    headers.push_back(pair<string, string>(h.name, h.value));
    return static_cast<T&> (*this);
  }
};
/* Something that contains query params */
template<class T> class WithQuery {
    KeyVal query_params;
public:
    virtual T &operator <<(const Param &q) {
      query_params.push_back(pair<string, string>(q.name, q.value));
      return static_cast<T&> (*this);
    }
    const KeyVal &get_query() const {return query_params;}
};
/* Http Request has both headers and query parameters */
class Request: public WithQuery<Request>, public WithHeaders<Request> {...};

这样我希望能够做request << Header(name, value) << Param("page", "1")之类的事情(稍后将在相应的Response类中重用WithHeaders)。

我正在尝试编译的代码是:

Request rq = Request("unused", "unused", "unused");
rq << Header("name", "value");

但是,我得到:

test/test_client.cpp:15:30: error: request for member ‘operator<<’ is ambiguous
In file included from test/test_client.cpp:1:0:
test/../client.h:45:16: error: candidates are: 
    T& WithQuery<T>::operator<<(const Param&) [with T = Request]         
    T& WithHeaders<T>::operator<<(const Header&) [with T = Request]

我一定错过了一些东西,但在编译期间似乎很容易区分ParamHeader。所以,问题是:

  • 为什么会失败以及如何修复?
  • 这是一件合理的事情,还是有一个更简单的设计?

我相信它应该有效,所以它很可能是一个 GCC 错误正如@refp在评论中指出的那样,查找实际上是模棱两可的,GCC 拒绝它是正确的。

这是您使其工作的方式:

class Request: public WithQuery<Request>, public WithHeaders<Request> {
public:
    using WithHeaders<Request>::operator<<;
    using WithQuery<Request>::operator<<;
};

现场示例