daldegam / eos-portable-archive

10 stars 7 forks source link

error: no type named ‘bits’ in ‘traits’ {aka ‘struct boost::math::detail::fp_traits_native<double>’} #5

Open romariorios opened 3 years ago

romariorios commented 3 years ago

A little background: I'm updating boost 1.67 to 1.74. I also updated eos-portable-archive from a previous version that didn't support boost >= 1.69 to the most recent one.

So, in portable_oarchive.hpp, we have these asserts around line 393 in the save overload that saves floating point numbers:

        template <typename T>
        typename boost::enable_if<boost::is_floating_point<T> >::type
        save(const T & t, dummy<3> = 0)
        {
            typedef typename fp::detail::fp_traits<T>::type traits;

            /** <snip> **/

            typename traits::bits bits;
            BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T));
            BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_iec559);

Before updating, everything worked fine. After updating, I'm hit with an error that says the bits member of traits in the snippet above is not a member of boost::math::detail::fp_traits_native<double>:

/dependencies_directory/eos_portable_archive/eos/portable_oarchive.hpp:393:26: error: no type named ‘bits’ in ‘traits’ {aka ‘struct boost::math::detail::fp_traits_native<double>’}
    typename traits::bits bits;

Right before the asserts, there's a comment that says that, if I got to this point in the code, one of the following was likely the problem:

  1. I'm serializing a long double which is not portable (not the case)
  2. I'm serializing a double but have no 64 bit integer (not the case)
  3. My machine is using an unknown floating point format (unlikely? It's just a 64 bit CentOS 6)

These comments assume I even get to the asserts below anyway, which I don't, so I believe this is something else? Also, these checks were in place in the previous version of boost + eos, so I don't think it has anything to do with my architecture.

Anyway, I went and checked which traits struct was this and then I get this in boost/math/special_functions/detail/fp_traits.hpp:

template<class T> struct fp_traits_native
{
    typedef native_tag method;
};

It's just a tag type. For some reason, the native traits struct is being selected, but it clearly isn't expected here.

In the header section of portable_oarchive.hpp, I see this:

// endian and fpclassify
#if BOOST_VERSION < 103600
#include <boost/integer/endian.hpp>
#include <boost/math/fpclassify.hpp>
#elif BOOST_VERSION < 104800
#include <boost/spirit/home/support/detail/integer/endian.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#elif BOOST_VERSION >= 106900
#define BOOST_MATH_DISABLE_STD_FPCLASSIFY
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/endian/conversion.hpp>
#else
#include <boost/spirit/home/support/detail/endian/endian.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#endif

If I go over to fpclassify.hpp:

template<class T> struct fp_traits
{
    typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T), ::boost::is_floating_point<T>::value>::type precision;
#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
    typedef typename select_native<T>::type type;
#else
    typedef fp_traits_non_native<T, precision> type;
#endif
    typedef fp_traits_non_native<T, precision> sign_change_type;
};

Since BOOST_MATH_DISABLE_STD_FPCLASSIFY is defined, shouldn't it choose the fp_traits_non_native traits struct? Why is it choosing the native one? I'm not sure what's going on.

And this is as far as I've got. I'm lost at what is happening here and I'm not familiar with this code.

I hope this helps you investigate.

romariorios commented 3 years ago

Oh, I almost forgot:

Compiler (from RedHat's devtoolset-8):

$ gcc --version
gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

OS:

$ lsb_release -a
LSB Version:    :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID: CentOS
Description:    CentOS release 6.10 (Final)
Release:    6.10
Codename:   Final
$ uname -a
Linux hostname 2.6.32-754.35.1.el6.x86_64 #1 SMP Sat Nov 7 12:42:14 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Boost 1.74.0 from https://conan.io

guitargeek commented 1 year ago

I think this problem is solved best by using fp_traits_non_native explicitly in the eos-portable-archive code, like I also suggested here: https://github.com/cms-sw/cmssw/pull/40057