унаследованный конструктор шаблонов не вызывается

#c #templates #inheritance #constructor #c 17

#c #шаблоны #наследование #конструктор #c 17

Вопрос:

Я изучаю дизайн для проекта, и у меня есть проблема, которую нужно преодолеть. В принципе, мне нужно вызвать конструктор шаблонов visitor_interfaces_t . Ниже приведен упрощенный пример синтаксической работы системы. «Крупномасштабный» проект находится по адресу https://github.com/amatarazzo777/ux_gui_stream и находится в разработке самостоятельно. Объекты организованы так, чтобы их было легко создавать, а также поддерживать. Поэтому мне нравится синтаксис того, как пишется coordinate_t . Однако он работает не так, как я планировал. Каков правильный способ наследовать visitor_interfaces_t и разрешить вызывать конструктор пакета параметров шаблона для него? Диалект C 17. Также приветствуется любое другое тщательное разбиение, например, улучшение дизайна. Заранее спасибо за помощь.

Я нашел другое решение этого вопроса. Я решил разбить процесс трансляции позиции интерфейса и разрешения функции-члена на реализацию.

файл заголовка шаблона (templates_inherit.h)

 /**
  templates_inherit.h

*/

#ifndef TEMPLATES_INHERIT_H_
#define TEMPLATES_INHERIT_H_

typedef int cairo_t;
typedef double PangoLayout;
class system_base_t {
public:
  system_base_t() {
    if (!visitor_dispatch_bound)
      ;
  }
  virtual ~system_base_t() {}

  bool visitor_dispatch_bound = false;
};

template <typename T, typename TC, typename... Args>
class class_storage_emitter_t : public TC,
                                public Args...,
                                public system_base_t {
public:
  using TC::TC;
  class_storage_emitter_t() {}

  class_storage_emitter_t(const class_storage_emitter_t amp;other) : TC(other) {}

  class_storage_emitter_t(class_storage_emitter_t amp;amp;other) noexcept
      : TC(other) {}

  class_storage_emitter_t amp;operator=(const class_storage_emitter_t amp;other) {
    TC::operator=(other);
    return *this;
  }

  class_storage_emitter_t amp;operator=(class_storage_emitter_t amp;amp;other) noexcept {
    TC::operator=(other);
    return *this;
  }

  virtual ~class_storage_emitter_t() {}
};

typedef std::function<void(cairo_t *)> fn_emit_cr_t;
typedef std::function<void(PangoLayout *)> fn_emit_layout_t;

typedef std::variant<std::monostate, fn_emit_cr_t, fn_emit_layout_t>
    fn_emit_overload_t;

class visitor_interface_t {
public:
  fn_emit_overload_t fn = {};
  std::size_t pipeline_order = {};
  virtual void bind_dispatch(system_base_t *ptr) {}
};

class visitor_interfaces_base_t {
public:
  visitor_interfaces_base_t() {}
  virtual ~visitor_interfaces_base_t() {}

  std::unordered_map<std::type_index, visitor_interface_t *>
      accepted_interfaces = {};
};

template <typename... Args>
class visitor_interfaces_t : public visitor_interfaces_base_t, public Args... {
public:
  visitor_interfaces_t() : Args(this)... {}
};

// abstract classes. started having problems when I added
// "interface" function (clue)
template <std::size_t ORDER> class abstract_emit_cr_t : visitor_interface_t {
public:
  abstract_emit_cr_t(visitor_interfaces_base_t *ptr) {
    pipeline_order = ORDER;
    ptr->accepted_interfaces[std::type_index(typeid(fn_emit_cr_t))] = this;
  }
  void bind_dispatch(system_base_t *ptr) {
    fn = fn_emit_cr_t{std::bind(amp;abstract_emit_cr_t::emit,
                                dynamic_cast<abstract_emit_cr_t *>(ptr),
                                std::placeholders::_1)};
  }
  virtual ~abstract_emit_cr_t() {}
  virtual void emit(cairo_t *cr) = 0;
};

template <std::size_t ORDER>
class abstract_emit_layout_t : visitor_interface_t {
public:
  abstract_emit_layout_t() {}
  abstract_emit_layout_t(visitor_interfaces_base_t *ptr) {
    pipeline_order = ORDER;
    ptr->accepted_interfaces[std::type_index(typeid(fn_emit_layout_t))] = this;
  }
  void bind_dispatch(system_base_t *ptr) {
    fn = fn_emit_layout_t{std::bind(amp;abstract_emit_layout_t::emit,
                                    dynamic_cast<abstract_emit_layout_t *>(ptr),
                                    std::placeholders::_1)};
  }
  virtual ~abstract_emit_layout_t() {}
  virtual void emit(PangoLayout *layout) = 0;
};

const int order_render_option = 3;

class coordinate_storage_t {
public:
  coordinate_storage_t() {}
  coordinate_storage_t(double _x, double _y, double _w, double _h)
      : x(_x), y(_y), w(_w), h(_h) {}
  coordinate_storage_t(double _x, double _y) : x(_x), y(_y) {}
  virtual ~coordinate_storage_t() {}
  double x = {};
  double y = {};
  double w = {};
  double h = {};
};

/**
 * classes are named and manufactured like so.
 * the parameterized nature of the syntax yields
 * a very maintainable source base.
 */
using coordinate_t = class coordinate_t
    : public class_storage_emitter_t<
          coordinate_t, coordinate_storage_t,
          visitor_interfaces_t<abstract_emit_cr_t<order_render_option>,
                               abstract_emit_layout_t<order_render_option>>> {
public:
  using class_storage_emitter_t::class_storage_emitter_t;
  coordinate_t() {}

  void emit(cairo_t *cr) { std::cout << "emit cr" << std::endl; }
  void emit(PangoLayout *layout) { std::cout << "emit layout" << std::endl; }
};

#endif /* TEMPLATES_INHERIT_H_ */
  

template_inherit.cpp

 
#include <functional>
#include <type_traits>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <iostream>
#include <any>
#include <variant>

#include "templates_inherit.h"

using namespace std;

int main() {
  coordinate_t pos = coordinate_t{10, 10, 500, 500};
  pos.init_dispatch();

  cout << pos.x << " " << pos.y << " " << pos.w << " " << pos.h << endl;
  cairo_t dummy_cr = 1;
  PangoLayout dummy_layout = 2;

  for (auto n : pos.accepted_interfaces) {
    std::visit(
        [amp;](auto amp;amp;arg) {
          using T = std::decay_t<decltype(arg)>;
          if constexpr (std::is_same_v<T, fn_emit_cr_t>)
            arg(amp;dummy_cr);
          else if constexpr (std::is_same_v<T, fn_emit_layout_t>)
            arg(amp;dummy_layout);
        },
        n.second->fn);
  }
  return 0;
}

  

Комментарии:

1. Это много кода. Для чего он предназначен? В чем ошибка?

2. Вы не передаете никаких аргументов, которые могли бы перейти к visitor_interfaces_t(Args amp;... args) . Четыре переданных вами аргумента идут напрямую coordinate_storage_t , и конструктор for class_storage_emitter_t никогда не вызывается, потому class_storage_emitter_t что у него нет конструктора, который принимает четыре аргумента. Откуда возьмутся аргументы для visitor_interfaces_t(Args amp;... args) , если вы их не передадите?

3. n. местоимения. Извините за объем кода, я хотел быть уверенным, что там будет полная архитектура. Код предназначен для именования объектов, которые могут быть вставлены в поток с использованием оператора <<, который не включен в другую часть базы кода. У меня есть несколько объектов, которые пользователь может создать для предоставления вывода gui с использованием Cairo и Pango. Так, например, есть text_font_t , text_color_t и image_block_t .

4. Джерри, я думал, что аргументы будут поступать из списка наследования в объявлении класса. Но вы правы, конструктор шаблонов никогда не вызывается. Как я мог бы инкапсулировать класс, чтобы определение поддерживало visitor_interfaces_t и вызывало его локально?

5. n. местоимения. эти объекты относятся к разным частям этапа рендеринга. то есть шрифт должен быть загружен и создан до его использования. некоторые объекты имеют разные значения для частей этапа рендеринга, поэтому упоминается порядок рендеринга. Опубликованный интерфейс предоставляет шаблон посетителя.