c++ - 为什么 C++ 模板实例化失败?

标签 c++ linux inheritance gcc c++17

RefPerSys适用于 Linux/x86-64 的 GPLv3+ 项目 (在 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 相关代码相关,这是一些 HTTP 服务器库(具有命名空间 Onion::),它是 #include正在refpersys.hh标题。
在 C++ 意义上没有使用多重继承。
我们有一个枚举 Rps_Type (在文件 refpersys.hh 第 903 行)定义一些 tagged union 的标签类型。标记的 union 类型是顶级 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 (在 refpersys.hh:1964 中)是 Rps_ZoneValue 的子类.让我们将 RefPerSys 对象调用为该 Rps_ObjectZone 的子类的任何 C++ 实例。 .class Rps_ObjectRef (在 refpersys.hh:694 中)是我们的 GC-ed 智能指针,指向 Rps_ObjectZone .class Rps_Value (在 refpersys.hh:967 中)是一个单字智能指针(有点像在 Common Lisp 中, SBCL -value 之类)。class Rps_Payload (在 refpersys.hh:2264 中)在 Rps_ObjectZone 中携带一些可选的额外数据.每个这样的有效负载都属于一个 RefPerSys 对象(一些 Rps_ObjectZone),称为其所有者。put_new_arg3_payload Rps_ObjectZone的模板成员函数很简单(在 refpersys.hh:2157 和以下几行中)与 ob_payloadRps_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
许多 Web 交互(即 HTTP 请求,在 C++ 中为 Onion::Request ,以及相应的 HTTP 回复,在 C++ 中为 Onion::Reply,本身是 C++ std::ostream 的子类)被具体化为 class Rps_PayloadWebex 的 C++ 实例在文件中声明 headweb_rps.hh第 65 行,以及 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_ProtoCallFrameRps_TypedZone 的子类定义于 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 && 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"
                , "\n\n" "%s*** RefPerSys ASSERT failed: %s%s\n" "%s:%d: {%s}\n\n", (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[1m"):""),
                "(callerframe != nullptr && callerframe->is_good_call_frame())",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[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"
                , "\n\n" "%s*** RefPerSys ASSERT failed: %s%s\n" "%s:%d: {%s}\n\n",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[1m"):""), "(req != nullptr)",
                (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[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"
              , "\n\n" "%s*** RefPerSys ASSERT failed: %s%s\n" "%s:%d: {%s}\n\n",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[1m"):""), "(resp != nullptr)",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[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 & (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));
  auto& _f = *_.fieldsptr();


  ;
  _f.obwebex = Rps_ObjectRef::make_object(&_, web_exchange_ob);
  auto paylwebex =
    _f.obwebex->put_new_arg3_payload<Rps_PayloadWebex>(reqnum,req,resp);
  do { if ((rps_debug_flags & (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"
              , "\n\n" "%s*** RefPerSys ASSERT failed: %s%s\n" "%s:%d: {%s}\n\n",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[1m"):""), "(paylwebex != nullptr)",
              (rps_stderr_istty?(rps_without_terminal_escape?"":"\033[0m"):""), "httpweb_rps.cc",317,__PRETTY_FUNCTION__);
      rps_fatal_stop_at("httpweb_rps.cc",317); }} while(0);
  return _f.obwebex;
} // end PayloadWebex::make_obwebex
我究竟做错了什么?

最佳答案

错误消息末尾的这一行很清楚,它暗示 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 int&, Onion::Request*&, Onion::Response*&)’
这是第一行错误:
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必须可转换为 ZoneClass* ,这意味着有问题的代码在不应该声明的地方声明了模板参数类型。

关于c++ - 为什么 C++ 模板实例化失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64692976/

相关文章:

python - 计算 sigmoid 最快的方法是什么?

c++ - 正确使用 rand()?

c++ - 硬编码应用程序中的资源

c++ - 防止 .lib 在运行时加载 DLL

c++ - 基于策略的设计中的模糊继承

linux - 替换文件每一行中的每个第二个单词实例

linux - ODBC lib 无法加载指定的驱动程序

mysql - 确定 CentOS 6 Apache 服务器运行缓慢的问题

c# - 如何在 C# 中使继承的不可变属性可变?

asp.net - NHibernate 继承类但无需持久化