在RefPerSys GPLv3+Linux/x86-64项目中(在Debian/Sid系统上(,git commit 37172c9af257865d,使用GCC 10编译,调用为g++ -std=gnu++17 -Og -g3 -Wall -Wextra
等。我收到以下错误消息:
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 int&, Onion::Request*&, Onion::Response*&)’
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);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
我不容易举一个小例子,但我能够给出以下解释。它是关于用多线程实现(和web接口,以及我们的精确跟踪垃圾收集器(来实现一些动态类型语言(类似专家系统的规则,语义上受Common Lisp的启发(。
主头文件是refpersys.hh
,到处都是#include
d。伴随头文件是headweb_rps.hh
,仅与使用libonion的web相关代码相关,libonion是某种HTTP服务器库(名称空间为Onion::
(,它是refpersys.hh
头的#include
。
没有在C++意义上使用多重继承。
我们有一个枚举Rps_Type
(在文件refpersys.hh
的第903行(,它定义了某个标记的并集类型的标记。该标记的并集类型是顶级Rps_TypedZone
(在文件refpersys.hh
的第1630行中(,具有在refpersys.hh
的第1637行中定义的明显构造函数Rps_TypedZone::Rps_TypedZone(const Rps_Type ty)
。
我们有一个Rps_TypedZone
的class Rps_QuasiZone
子类(在文件refpersys.hh
的第1646行(。
我们有Rps_QuasiZone
的一个class Rps_ZoneValue
(在refpersys.hh:1755
中(子类。
class Rps_ObjectZone
(在refpersys.hh:1964
中(是Rps_ZoneValue
的一个子类。让我们调用RefPerSys对象该Rps_ObjectZone
的子类的任何C++实例。
class Rps_ObjectRef
(在refpersys.hh:694
中(是我们指向Rps_ObjectZone
的GC ed智能指针。
class Rps_Value
(在refpersys.hh:967
中(是一个单字智能指针(有点像Common Lisp中的SBCL值(。
class Rps_Payload
(在refpersys.hh:2264
中(在Rps_ObjectZone
内携带一些可选的额外数据。每个这样的有效载荷都属于一个RefPerSys对象(一些Rps_ObjectZone
(,称为其所有者。
Rps_ObjectZone
的put_new_arg3_payload
模板成员函数很简单(在refpersys.hh:2157
和以下行中(,ob_payload
是Rps_ObjectZone
的成员字段,在refpersys.hh:1981
:行中声明为std::atomic<Rps_Payload*> ob_payload;
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
许多web交互(即HTTP请求,在C++中某些Onion::Request
,以及相应的HTTP回复,在C++某些Onion::Reply
中,其本身是C++std::ostream
的子类(被具体化为文件headweb_rps.hh
第65行中声明的class Rps_PayloadWebex
的C++实例和Rps_Payload
的子类。
模板成员函数Rps_QuasiZone::rps_allocate4
(在第refpersys.hh:1699
行(定义为:
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);
};
我们的";口译员";具体化为class Rps_ProtoCallFrame;
,我们(在refpersys.hh
第691行(有一个typedef Rps_ProtoCallFrame Rps_CallFrame;
class Rps_ProtoCallFrame
是refpersys.hh:2823
中定义的Rps_TypedZone
的一个子类。
故障线路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 && 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(&_, 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
&& 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?"":"