C++ overloading operator with multiple inheritance from templates

倾然丶 夕夏残阳落幕 提交于 2019-12-17 20:14:36

问题


I have an hierarchy that represents some part of an HTTP client and looks like this:

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> {...};

So that I expected to be able to do things like request << Header(name, value) << Param("page", "1") (and later will reuse WithHeaders in the corresponding Response class).

The code that I'm trying to compile is:

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

However, I get:

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]

I must be missing something, but it seems quite easy to distinguish Param from Header during the compilation time. So, the questions are:

  • why does it fail and how to fix it?
  • is that a reasonable thing to do at all or there's a simpler design?

回答1:


I believe it should work, so it's most likely a GCC bug. As pointed out by @refp in the comments, the lookup is actually ambiguous and GCC is correct in rejecting it.

This is how you make it work:

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

Live example



来源:https://stackoverflow.com/questions/19159784/c-overloading-operator-with-multiple-inheritance-from-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!