Почему создание экземпляра шаблона C завершается с ошибкой?

#c #linux #inheritance #gcc #c 17

#c #linux #наследование #gcc #c 17

Вопрос:

В проекте RefPerSys GPLv3 для Linux / x86-64 (в системе Debian / Sid) git фиксирует 37172c9af257865d, компилируется с помощью GCC 10, вызывается как g -std=gnu 17 -Og -g3 -Wall -Wextra etc… Я получаю следующее сообщение об ошибке:

   refpersys.hh: In instantiation of ‘PaylClass* Rps_ObjectZone::put_new_arg3_payload(Arg1Class, Arg2Class, Arg3Class) [with PaylClass = Rps_PayloadWebex; Arg1Class = long unsigned int; Arg2Class = Onion::Request*; Arg3Class = Onion::Response*]’:
  httpweb_rps.cc:314:71:   required from here
  refpersys.hh:2162:76: error: no matching function for call to ‘Rps_ObjectZone::rps_allocate4<Rps_PayloadWebex, long unsigned int, Onion::Request*, Onion::Response*>(Rps_ObjectZone*, long unsigned intamp;, Onion::Request*amp;, Onion::Response*amp;)’
   2162 | Zone::rps_allocate4<PaylClass,Arg1Class,Arg2Class,Arg3Class>(this,arg1,arg2,arg3);
        | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~

  In file included from headweb_rps.hh:37,
                   from httpweb_rps.cc:34:
  refpersys.hh:1701:3: note: candidate: ‘template<class ZoneClass, class Arg1Class, class Arg2Class, class Arg3Class, class Arg4Class> static ZoneClass* Rps_QuasiZone::rps_allocate4(Arg1Class, Arg2Class, Arg3Class, Arg4Class)’
   1701 |   rps_allocate4(Arg1Class arg1, Arg2Class arg2, Arg3Class arg3, Arg4Class arg4)
        |   ^~~~~~~~~~~~~
  refpersys.hh:1701:3: note:   template argument deduction/substitution failed:
  In file included from headweb_rps.hh:37,
                   from httpweb_rps.cc:34:
  refpersys.hh:2162:76: note:   cannot convert ‘(Rps_ObjectZone*)this’ (type ‘Rps_ObjectZone*’) to type ‘long unsigned int2162 | Zone::rps_allocate4<PaylClass,Arg1Class,Arg2Class,Arg3Class>(this,arg1,arg2,arg3);
        | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
  

Мне нелегко привести небольшой пример, но я способен дать следующие объяснения. Речь идет о реализации некоторого динамически типизированного языка (правила, подобные экспертной системе, семантически вдохновленные Common Lisp) с многопоточной реализацией (и веб-интерфейсом, с нашим сборщиком мусора точной трассировки).

Основной заголовочный файл является refpersys.hh и является #include общим везде. Сопутствующий заголовочный файл имеет headweb_rps.hh отношение только к веб-коду, использующему libonion, который представляет собой некоторую библиотеку HTTP-сервера (с пространством Onion:: имен), и он является #include refpersys.hh заголовком.

Множественное наследование не используется в смысле C .

У нас есть перечисление Rps_Type refpersys.hh строке файла 903), определяющее тег некоторого типа объединения с тегами. Этот помеченный тип объединения является верхним классом Rps_TypedZone refpersys.hh строке файла 1630) с очевидным конструктором Rps_TypedZone::Rps_TypedZone(const Rps_Type ty) , определенным в refpersys.hh строке 1637.

У нас есть class Rps_QuasiZone подкласс Rps_TypedZone refpersys.hh строке файла 1646).

У нас есть class Rps_ZoneValue refpersys.hh:1755 ) подкласс Rps_QuasiZone .

class Rps_ObjectZone (in refpersys.hh:1964 ) является подклассом Rps_ZoneValue . Давайте назовем объектами RefPerSys любой экземпляр C подкласса этого Rps_ObjectZone .

class Rps_ObjectRef (in refpersys.hh:694 ) — это наш интеллектуальный указатель GC-ed на Rps_ObjectZone .

class Rps_Value (in refpersys.hh:967 ) — это интеллектуальный указатель из одного слова (немного похожий на Common Lisp, SBCL-значение, подобное).

class Rps_Payload (in refpersys.hh:2264 ) содержит некоторые необязательные дополнительные данные внутри Rps_ObjectZone . Каждая такая полезная нагрузка принадлежит одному объекту RefPerSys (some Rps_ObjectZone ), называемому его владельцем.

Функция- put_new_arg3_payload член шаблона of Rps_ObjectZone просто (в refpersys.hh:2157 и после строк) ob_payload является полем-членом Rps_ObjectZone , объявленным как std::atomic<Rps_Payload*> ob_payload; в строке refpersys.hh:1981 :

   PaylClass* put_new_arg3_payload(Arg1Class arg1, Arg2Class arg2, Arg3Class arg3)
  {
    std::lock_guard<std::recursive_mutex> gu(ob_mtx);
    PaylClass*newpayl =
      Rps_QuasiZone::rps_allocate4<PaylClass,Arg1Class,Arg2Class,Arg3Class>(this,arg1,arg2,arg3);
    Rps_Payload*oldpayl = ob_payload.exchange(newpayl);
    if (oldpayl)
      delete oldpayl;
    return newpayl;
  };                // end put_new_arg3_payload
  

Many web interactions (that is an HTTP request, in C some Onion::Request , and the corresponding HTTP reply, in C some Onion::Reply , itself a subclass of C std::ostream ) are reified as C instances of class Rps_PayloadWebex declared in file headweb_rps.hh line 65, and subclass of Rps_Payload .

The template member function Rps_QuasiZone::rps_allocate4 is defined (at line refpersys.hh:1699 ) as:

 template <typename ZoneClass, typename Arg1Class, typename Arg2Class, typename Arg3Class, typename Arg4Class>
static ZoneClass*
rps_allocate4(Arg1Class arg1, Arg2Class arg2, Arg3Class arg3, Arg4Class arg4)
{
  return new(nullptr) ZoneClass(arg1, arg2, arg3, arg4);
};
  

The call frames of our «interpreter» are reified as class Rps_ProtoCallFrame; and we have (in refpersys.hh line 691) a typedef Rps_ProtoCallFrame Rps_CallFrame;

The class Rps_ProtoCallFrame is a subclass of Rps_TypedZone defined in refpersys.hh:2823 .

Ошибочная строка httpweb_rps.cc:314 находится внутри:

  Rps_ObjectRef
 Rps_PayloadWebex::make_obwebex(Rps_CallFrame*callerframe, Onion::Request*req, Onion::Response*resp,
                                uint64_t reqnum)
 {
   RPS_ASSERT(callerframe != nullptr amp;amp; callerframe->is_good_call_frame());
   RPS_ASSERT(req != nullptr);
   RPS_ASSERT(resp != nullptr);
   auto web_exchange_ob = RPS_ROOT_OB(_8zNtuRpzXUP013WG9S);
   RPS_DEBUG_LOG(WEB, "Rps_PayloadWebex::make_obwebex start reqnum#" << reqnum
                );
   RPS_LOCALFRAME(/*descr:*/ web_exchange_ob,
                             /*prev:*/callerframe,
                             /*locals:*/
                             Rps_ObjectRef obwebex);
   _f.obwebex = Rps_ObjectRef::make_object(amp;_, web_exchange_ob);
   auto paylwebex = ////////////////////////////////////// FAULTY LINE BELOW
     _f.obwebex->put_new_arg3_payload<Rps_PayloadWebex>(reqnum,req,resp);
   RPS_DEBUG_LOG(WEB, "Rps_PayloadWebex::make_obwebex end reqnum#" << reqnum
                 << " obwebex=" << _f.obwebex << " startim:" <<  paylwebex->webex_startim);
   RPS_ASSERT(paylwebex != nullptr);
   return _f.obwebex;
 } // end PayloadWebex::make_obwebex
  

В приведенном выше коде, RPS_ASSERT , RPS_ROOT_OB , RPS_LOCALFRAME , RPS_DEBUG_LOG являются макросами C . Макрорасширение приведенного выше кода:

 Rps_ObjectRef
Rps_PayloadWebex::make_obwebex(Rps_CallFrame*callerframe, Onion::Request*req, Onion::Response*resp,
                               uint64_t reqnum)
{
  do { if (__builtin_expect(!!(!((callerframe != nullptr
                                  amp;amp; callerframe->is_good_call_frame()))),0))
      { fprintf(
                //# 302 "httpweb_rps.cc" 3
                stderr
                //# 302 "httpweb_rps.cc"
                , "nn" "%s*** RefPerSys ASSERT failed: %s%sn" "%s:%d: {%s}nn", (rps_stderr_istty?(rps_without_terminal_escape?"":"33[1m"):""),
                "(callerframe != nullptr amp;amp; callerframe->is_good_call_frame())",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"33[0m"):""),
                "httpweb_rps.cc",302,__PRETTY_FUNCTION__);
        rps_fatal_stop_at("httpweb_rps.cc",302); }}
  while(0);
  do
    { if (__builtin_expect(!!(!((req != nullptr))),0)) {
        fprintf(
                //# 303 "httpweb_rps.cc" 3
                stderr
                //# 303 "httpweb_rps.cc"
                , "nn" "%s*** RefPerSys ASSERT failed: %s%sn" "%s:%d: {%s}nn",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"33[1m"):""), "(req != nullptr)",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"33[0m"):""), "httpweb_rps.cc",303,__PRETTY_FUNCTION__);
        rps_fatal_stop_at("httpweb_rps.cc",303); }} while(0);
  do { if (__builtin_expect(!!(!((resp != nullptr))),0)) {
      fprintf(
              //# 304 "httpweb_rps.cc" 3
              stderr
              //# 304 "httpweb_rps.cc"
              , "nn" "%s*** RefPerSys ASSERT failed: %s%sn" "%s:%d: {%s}nn",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"33[1m"):""), "(resp != nullptr)",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"33[0m"):""), "httpweb_rps.cc",304,__PRETTY_FUNCTION__);
      rps_fatal_stop_at("httpweb_rps.cc",304); }} while(0);
  auto web_exchange_ob = rps_rootob_8zNtuRpzXUP013WG9S;
  do { if ((rps_debug_flags amp; (1 << RPS_DEBUG_WEB)))
      { std::ostringstream _logstream_306;
        _logstream_306 << "Rps_PayloadWebex::make_obwebex start reqnum#" << reqnum << std::flush;
        rps_debug_printf_at("httpweb_rps.cc", 306, RPS_DEBUG_WEB,
                            "%s", _logstream_306.str().c_str()); } } while (0)
    ;
  struct RpsFrameData308 {/*locals:*/ Rps_ObjectRef obwebex; };
  typedef Rps_FieldedCallFrame<RpsFrameData308> Rps_FldCallFrame308;
  class Rps_FrameAt308 : public Rps_FldCallFrame308
  { public:
    Rps_FrameAt308(Rps_ObjectRef obd308, Rps_CallFrame* prev308) :
      Rps_FldCallFrame308(obd308, prev308) { }; };
  Rps_FrameAt308 _((/*descr:*/ web_exchange_ob),(/*prev:*/callerframe));
  autoamp; _f = *_.fieldsptr();


  ;
  _f.obwebex = Rps_ObjectRef::make_object(amp;_, web_exchange_ob);
  auto paylwebex =
    _f.obwebex->put_new_arg3_payload<Rps_PayloadWebex>(reqnum,req,resp);
  do { if ((rps_debug_flags amp; (1 << RPS_DEBUG_WEB)))
      { std::ostringstream _logstream_315;
        _logstream_315 << "Rps_PayloadWebex::make_obwebex end reqnum#"
                       << reqnum << " obwebex=" << _f.obwebex << " startim:"
                       << paylwebex->webex_startim << std::flush; rps_debug_printf_at("httpweb_rps.cc",
                                                                                      315, RPS_DEBUG_WEB, "%s",
                                                                                      _logstream_315.str().c_str()); } } while (0)
    ;
  do { if (__builtin_expect(!!(!((paylwebex != nullptr))),0)) {
      fprintf(
              //# 317 "httpweb_rps.cc" 3
              stderr
              //# 317 "httpweb_rps.cc"
              , "nn" "%s*** RefPerSys ASSERT failed: %s%sn" "%s:%d: {%s}nn",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"33[1m"):""), "(paylwebex != nullptr)",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"33[0m"):""), "httpweb_rps.cc",317,__PRETTY_FUNCTION__);
      rps_fatal_stop_at("httpweb_rps.cc",317); }} while(0);
  return _f.obwebex;
} // end PayloadWebex::make_obwebex
  

Что я делаю не так?

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

1. Почему голосование за закрытие? Я изо всех сил старался предоставить минимальную, но необходимую информацию! Если бы я смог упростить эту проблему, я, вероятно, решил бы ее сам.

Ответ №1:

Эта строка в конце сообщения об ошибке понятна, она намекает на то, что long unsigned int следует искать…

 cannot convert ‘(Rps_ObjectZone*)this’ (type ‘Rps_ObjectZone*’) to type ‘long unsigned int 

Это связано с этой строкой в начале сообщения об ошибке:

 refpersys.hh:2162:76: error: no matching function for call to Rps_ObjectZone::rps_allocate4<Rps_PayloadWebex, long unsigned int, Onion::Request*, Onion::Response*>(Rps_ObjectZone*, long unsigned intamp;, Onion::Request*amp;, Onion::Response*amp;)’
  

И это первая строка ошибки:

 refpersys.hh: In instantiation of ‘PaylClass* Rps_ObjectZone::put_new_arg3_payload(Arg1Class, Arg2Class, Arg3Class) [with PaylClass = Rps_PayloadWebex; Arg1Class = long unsigned int; Arg2Class = Onion::Request*; Arg3Class = Onion::Response*
  

Важной частью является Arg1Class = long unsigned int;

Все это означает, что long unsigned int (тип переменной reqnum не является допустимым типом для первого параметра в вашем вызове _f.obwebex->put_new_arg3_payload<Rps_PayloadWebex>();

Кажется, что ArgClass1 должен быть по крайней мере каким-то указателем и, что еще более вероятно, указателем на тип, производный от Rps_ObjectZone .

Я не использовал эту конкретную библиотеку, но именно это означает сообщение об ошибке.

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

    Rps_QuasiZone::rps_allocate4<PaylClass,Arg1Class,Arg2Class,Arg3Class> (this,arg1,arg2,arg3);
  

Либо там, либо в вызове конструктора для класса ZoneClass .

Смешанный порядок параметров — это только предположение, я не видел вашего конструктора для класса ZoneClass .

В качестве примечания: если Arg1Class ДОЛЖНО быть преобразовано в a ZoneClass* , это означает, что рассматриваемый код объявляет типы параметров шаблона там, где этого не должно быть.