"auto" 在 hashtable_policy.h 中推断出不正确的类型
"auto" deducing incorrect type in hashtable_policy.h
我正在构建一对工具,gridlab-d and HELICS,前者使用后者的共享库。在成功 building/installing 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);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
正在调查有问题的 header,这是它抱怨的代码:
// 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_width
的 auto
类型似乎被错误地推断为 double
类型,而不是 size_t
类型(这应该可以从std::min<size_t>
的类型)。如果我复制 header,然后编辑它以将 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 是根据说明构建的。
很高兴提供额外的信息,任何帮助解决这个问题而不需要用户修改他们的标准 headers 将不胜感激。
更新: 这是根文件 helics_msg.cpp
的 pre-processed 输出,具有它抱怨的特定功能。我没有看到任何会导致错误的宏观有趣业务。完整文件位于 here as a gist,片段从第 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 redefines min
to fmin
:
#define min fmin /**< min macro */
因此,只要包含 platform.h
,min
就会被 fmin
替换。这只是一个有根据的猜测,因为我手头没有你确切的包含图。
不幸的是,std::fmin
will always return a double on integral values. This is a defect in gridlab-d and should be reported—as you already did。
我正在构建一对工具,gridlab-d and HELICS,前者使用后者的共享库。在成功 building/installing 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);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
正在调查有问题的 header,这是它抱怨的代码:
// 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_width
的 auto
类型似乎被错误地推断为 double
类型,而不是 size_t
类型(这应该可以从std::min<size_t>
的类型)。如果我复制 header,然后编辑它以将 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 是根据说明构建的。
很高兴提供额外的信息,任何帮助解决这个问题而不需要用户修改他们的标准 headers 将不胜感激。
更新: 这是根文件 helics_msg.cpp
的 pre-processed 输出,具有它抱怨的特定功能。我没有看到任何会导致错误的宏观有趣业务。完整文件位于 here as a gist,片段从第 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 redefines min
to fmin
:
#define min fmin /**< min macro */
因此,只要包含 platform.h
,min
就会被 fmin
替换。这只是一个有根据的猜测,因为我手头没有你确切的包含图。
不幸的是,std::fmin
will always return a double on integral values. This is a defect in gridlab-d and should be reported—as you already did。