【问题标题】:"auto" deducing incorrect type in hashtable_policy.h“自动”推断 hashtable_policy.h 中的类型不正确
【发布时间】:2019-11-26 19:32:06
【问题描述】:

我正在构建一对工具,gridlab-dHELICS,前者使用后者的共享库。在成功构建/安装 HELICS 后编译 gridlab-d 时,出现以下错误:

In file included from /usr/include/c++/7/bits/hashtable.h:35:0,
             from /usr/include/c++/7/unordered_map:47,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/external/cereal/archives/../cereal.hpp:36,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/external/cereal/archives/portable_binary.hpp:32,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueConverter_impl.hpp:20,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueConverter.hpp:65,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueFederate.hpp:11,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/CombinationFederate.hpp:10,
             from connection/helics_msg.h:21,
             from connection/helics_msg.cpp:16:
/usr/include/c++/7/bits/hashtable_policy.h: In member function ‘std::size_t std::__detail::_Power2_rehash_policy::_M_next_bkt(std::size_t)’:
/usr/include/c++/7/bits/hashtable_policy.h:563:40: error: invalid operands of types ‘std::size_t {aka long unsigned int}’ and ‘double’ to binary ‘operator<<’
   const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1);
                          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/hashtable.h:35:0,
             from /usr/include/c++/7/unordered_map:47,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/external/cereal/archives/../cereal.hpp:36,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/external/cereal/archives/portable_binary.hpp:32,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueConverter_impl.hpp:20,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueConverter.hpp:65,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/ValueFederate.hpp:11,
             from /home/ericsilk/.local/helics-2.3.0/include/helics/application_api/CombinationFederate.hpp:10,
             from connection/helics_msg.h:21,
             from connection/init.cpp:16:
/usr/include/c++/7/bits/hashtable_policy.h: In member function ‘std::size_t std::__detail::_Power2_rehash_policy::_M_next_bkt(std::size_t)’:
/usr/include/c++/7/bits/hashtable_policy.h:563:40: error: invalid operands of types ‘std::size_t {aka long unsigned int}’ and ‘double’ to binary ‘operator<<’
   const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1);
                          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

调查有问题的标头,这是它抱怨的代码:

// Return a bucket size no smaller than n (as long as n is not above the
// highest power of 2).
std::size_t
_M_next_bkt(std::size_t __n) noexcept
{
  const auto __max_width = std::min<size_t>(sizeof(size_t), 8);
  const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1);
  std::size_t __res = __clp2(__n);

  if (__res == __n)
__res <<= 1;

  if (__res == 0)
__res = __max_bkt;

  if (__res == __max_bkt)
// Set next resize to the max value so that we never try to rehash again
// as we already reach the biggest possible bucket number.
// Note that it might result in max_load_factor not being respected.
_M_next_resize = std::size_t(-1);
  else
_M_next_resize
  = __builtin_ceil(__res * (long double)_M_max_load_factor);

  return __res;
}

因此,__max_widthauto 类型似乎被错误地推导出为 double 类型,而不是 size_t(应该可以从 std::min&lt;size_t&gt; 的类型中轻松推导出)。如果我复制标题,然后对其进行编辑以将auto 更改为size_t,则错误消失,确认这一点。

有趣的是,以下程序可以毫无问题地编译:

#include <iostream>
#include <algorithm>

int main()
{
    const auto __max_width = std::min<size_t>(sizeof(size_t), 8);
    const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1);

    std::cout << "__max_width: " << __max_width << std::endl;
    std::cout << "__max_bkt: " << __max_bkt << std::endl;

    return 0;
}

我在 Ubuntu 18.04 上,使用 gcc 7.4.0,虽然我在使用 clang 6.0.0 时遇到了同样的错误。我还确认这发生在 chroot 18.04 环境和另一台运行 WSL Ubuntu 18.04 的机器上。 HELICS 是使用 Python 接口和 HELICS_BUILD_CXX_SHARED_LIB 编译的,gridlab-d 是按照说明构建的。

很高兴提供更多信息,如果能在不要求用户修改其标准标题的情况下解决此问题,我们将不胜感激。

更新:这是根文件helics_msg.cpp 的预处理输出,以及它所抱怨的特定功能。我没有看到任何会导致错误的宏有趣的业务。完整文件位于here as a gist,sn-p 从第 72,722 行开始。它是一个大文件(>95k 行)。

    std::size_t
    _M_next_bkt(std::size_t __n) noexcept
    {
      const auto __max_width = std::
# 562 "/usr/include/c++/7/bits/hashtable_policy.h"
                                   fmin
# 562 "/usr/include/c++/7/bits/hashtable_policy.h" 3
                                      <size_t>(sizeof(size_t), 8);
      const auto __max_bkt = size_t(1) << (__max_width * 8 - 1);
      std::size_t __res = __clp2(__n);

      if (__res == __n)
 __res <<= 1;

      if (__res == 0)
 __res = __max_bkt;

      if (__res == __max_bkt)



 _M_next_resize = std::size_t(-1);
      else
 _M_next_resize
   = __builtin_ceil(__res * (long double)_M_max_load_factor);

      return __res;
    }

【问题讨论】:

  • 在 gridlab-d 和 HELICS 存储库根目录中运行 rgrep __CHAR_BIT__ 不会返回任何条目。编辑:这是对查看__CHAR_BIT__ 是否已在项目中重新定义的建议的回应。
  • 您是否尝试过使用 helics-2.3.0 中的所有包含的工作 sn-p?
  • 在 helics-2.3.0 目录中有将近 1k 的包含可用(主要是第 3 方),所以要全部完成会有点困难。但是,包括编译错误中列出的所有文件(CombinationFederate.hpp 等)不会导致相同的错误。
  • 您已经尝试过 grep,但也许可以尝试查看预处理文件,看看是否有 any 类型的宏恶作剧在干扰?
  • 我认为我做对了,我调用了make V=1 &gt; makeoutput.txt,然后找到了失败的命令,修改它以添加-E 选项,然后检查“connection/connection_connection_la-helics_msg.lo”的输出”。我搜索了函数 _M_next_bkt 并找到了定义,它包含在这个要点中:gist.github.com/esilksel/bdf36283926a0dae45540ee397eb11a1 我没有立即看到任何明显的东西。

标签: c++ c++14 auto cereal


【解决方案1】:

gridlab-d redefines min to fmin:

#define min fmin /**< min macro */

因此,只要包含 platform.hmin 就会被 fmin 替换。这只是一个有根据的猜测,因为我手头没有确切的包含图。

很遗憾,std::fmin will always return a double on integral values。这是 gridlab-d 的一个缺陷,应该报告——as you already did

【讨论】:

  • 我将构建包含图以进行验证和报告。谢谢!
  • @esilk 这只是在黑暗中拍摄,但您可以尝试用内联函数替换 #define。这可能有效。如果是,请向项目添加拉取请求。不幸的是,目前我手头没有合适的 C/C++ 环境,否则我会尝试复制问题并自行修复:/
猜你喜欢
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多