#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 int’
2162 | 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*
, это означает, что рассматриваемый код объявляет типы параметров шаблона там, где этого не должно быть.