Вернуть вложенный элемент шаблона в не шаблонный класс

Я хочу сделать класс событий, имеющий член любых типов данных, и сделать его не шаблонным классом. но он может устанавливать контент, предоставляя тип шаблона контента. У меня есть функции-обработчики, которые используют содержимое класса события.

Файл NewEvent.h

class NewEvent {
public:
  NewEvent(const int64_t& value = 0) : value_(value) {}

  int64_t value() const { return value_; }
  void set_value(const int64_t& value) { value_ = value; }

  class ElementBase {
  public:
    virtual ~ElementBase() {}
    template <typename ContentT> ContentT& content() const;
    template <typename ContentT> void set_content(const ContentT&);
  };

  template <typename ContentT, typename Allocator = std::allocator<ContentT>>
  class Element : public ElementBase {
  public:
    Element(const Allocator& alloc = Allocator()) : alloc_(alloc) {}

    typedef std::allocator_traits<Allocator> AllocatorTraits;

    ContentT& content() const {
      return content_;
    }
    void set_content(const ContentT& content) {
      AllocatorTraits::construct(alloc_, &content_, content);
    }

  protected:
    ContentT content_;
    Allocator alloc_;
  };

  template <typename ContentT>
  void set_content(ContentT& content) {
    ElementBase* element = new Element<ContentT>();
    element->set_content(content);
    content_.reset(element);
  }

  template <typename ContentT>
  ContentT& content() const {
    return content_->content<ContentT>();
  }

private:
  int64_t value_;

  std::unique_ptr<ElementBase> content_;
};

template <typename ContentT>
ContentT& NewEvent::ElementBase::content() const {
  return dynamic_cast<NewEvent::Element<ContentT>&>(*this).content();
}

template <typename ContentT>
void NewEvent::ElementBase::set_content(const ContentT& content) {
  dynamic_cast<NewEvent::Element<ContentT>&>(*this).set_content(content);
}

main.cpp

struct Data {
    int returns;
};
void print(Data data) {
}
int main() {
    struct Data data;
    // ...
    NewEvent new_event;
    new_event.set_content<Data>(data);

    print(new_event.content());
    return 0;
}

в моем коде функция set_content работает хорошо. но я не знаю, как получать content() и звонить в соответствии с типом контента. Функция content() в классе NewEvent имеет ошибку компиляции.

ошибка C2783: "ContentT &NewEvent::ElementBase::content(void) const": не удалось вывести аргумент шаблона для "ContentT"

Как решить эту проблему типа вывода, или есть другие методы для реализации, как это?

1 ответ

В вашей функции:

template <typename ContentT>
ContentT& content() const { .. }

ContentT здесь не может быть выведено - вы не предоставляете ничего, когда вы вызываете это, что компилятор может использовать, чтобы определить, какая версия content() позвонить (отсюда и ошибка). Как он может знать, хотите ли вы content<Date>() или же content<int>() или же...? Вы должны явно указать тип на сайте вызова так же, как вы это делали при вызове. set_content():

print(new_event.content<Date>()); // now compiler knows which content() to call.

(Обратите внимание, что то, что вы реализуете, фактически совпадает с boost::any на тот случай, если вы захотите использовать этот тип.)

Другие вопросы по тегам