“自动”推断出hashtable_policy.h

时间:2019-11-26 19:32:06

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

我正在构建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;
}

因此,似乎auto类型的__max_width被不正确地推导为double类型,而不是size_t(应该从std::min<size_t>)。如果我制作了标题的副本,然后对其进行编辑以将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;
}

我在使用gcc 7.4.0的Ubuntu 18.04上,尽管我在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,该代码段从第72,722行开始。它是一个大文件(> 9.5万行)。

    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;
    }

1 个答案:

答案 0 :(得分:2)

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