Opened 8 years ago

Closed 8 years ago

#11012 closed Bugs (fixed)

chrono_io v2 fail to compile with boost::chrono::duration< boost::rational<int> >

Reported by: Sébastien Barthélémy <barthelemy@…> Owned by: viboes
Milestone: Boost 1.58.0 Component: chrono
Version: Boost 1.57.0 Severity: Problem
Keywords: Cc:

Description

When using

 boost::chrono::duration< boost::rational<int> >

as duration type, chrono_io v2 fails to build with error

include/boost/chrono/io/duration_units.hpp:136:91: error: invalid static_cast from type ‘boost::chrono::duration<boost::rational<int> >::rep {aka boost::rational<int>}’ to type ‘intmax_t {aka long int}’

while chrono_io v1 builds and works as expected.

Here is the full compilation log for the attached example.

$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 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.

$ make
g++ -c -g -fPIC -Iinclude -I/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include -o src/chrono_rational.o src/chrono_rational.cc
In file included from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/time_point_put.hpp:16:0,
                 from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/time_point_io.hpp:22,
                 from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/chrono_io.hpp:26,
                 from src/chrono_rational.cc:5:
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp: In instantiation of ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put_value(boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’:
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:128:44:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(const boost::chrono::duration_units<CharT>&, boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&, const CharT*, const CharT*) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:168:81:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_io.hpp:135:15:   required from ‘std::basic_ostream<_CharT, _Traits>& boost::chrono::operator<<(std::basic_ostream<_CharT, _Traits>&, const boost::chrono::duration<Rep2, Period2>&) [with CharT = char; Traits = std::char_traits<char>; Rep = boost::rational<int>; Period = boost::ratio<1l>]’
src/chrono_rational.cc:11:18:   required from here
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:191:46: error: invalid static_cast from type ‘boost::chrono::duration<boost::rational<int> >::rep {aka boost::rational<int>}’ to type ‘long int’
             static_cast<long int> (d.count()));
                                              ^
In file included from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:15:0,
                 from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/time_point_put.hpp:16,
                 from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/time_point_io.hpp:22,
                 from /home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/chrono_io.hpp:26,
                 from src/chrono_rational.cc:5:
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_units.hpp: In instantiation of ‘boost::chrono::duration_units<CharT>::string_type boost::chrono::duration_units<CharT>::get_unit(boost::chrono::duration_style, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; boost::chrono::duration_units<CharT>::string_type = std::basic_string<char>]’:
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:230:70:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put_unit(const boost::chrono::duration_units<CharT>&, boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:133:56:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(const boost::chrono::duration_units<CharT>&, boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&, const CharT*, const CharT*) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:168:81:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_io.hpp:135:15:   required from ‘std::basic_ostream<_CharT, _Traits>& boost::chrono::operator<<(std::basic_ostream<_CharT, _Traits>&, const boost::chrono::duration<Rep2, Period2>&) [with CharT = char; Traits = std::char_traits<char>; Rep = boost::rational<int>; Period = boost::ratio<1l>]’
src/chrono_rational.cc:11:18:   required from here
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_units.hpp:127:87: error: invalid static_cast from type ‘boost::chrono::duration<boost::rational<int> >::rep {aka boost::rational<int>}’ to type ‘intmax_t {aka long int}’
         return do_get_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count()));

                                                                                       ^
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_units.hpp: In instantiation of ‘boost::chrono::duration_units<CharT>::string_type boost::chrono::duration_units<CharT>::get_n_d_unit(boost::chrono::duration_style, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; boost::chrono::duration_units<CharT>::string_type = std::basic_string<char>]’:
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:238:74:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put_unit(const boost::chrono::duration_units<CharT>&, boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:133:56:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(const boost::chrono::duration_units<CharT>&, boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&, const CharT*, const CharT*) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_put.hpp:168:81:   required from ‘boost::chrono::duration_put<CharT, OutputIterator>::iter_type boost::chrono::duration_put<CharT, OutputIterator>::put(boost::chrono::duration_put<CharT, OutputIterator>::iter_type, std::ios_base&, boost::chrono::duration_put<CharT, OutputIterator>::char_type, const boost::chrono::duration<Rep2, Period2>&) const [with Rep = boost::rational<int>; Period = boost::ratio<1l>; CharT = char; OutputIterator = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::iter_type = std::ostreambuf_iterator<char, std::char_traits<char> >; boost::chrono::duration_put<CharT, OutputIterator>::char_type = char]’
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_io.hpp:135:15:   required from ‘std::basic_ostream<_CharT, _Traits>& boost::chrono::operator<<(std::basic_ostream<_CharT, _Traits>&, const boost::chrono::duration<Rep2, Period2>&) [with CharT = char; Traits = std::char_traits<char>; Rep = boost::rational<int>; Period = boost::ratio<1l>]’
src/chrono_rational.cc:11:18:   required from here
/home/sbarthelemy/.local/share/qi/toolchains/linux64/boost/include/boost/chrono/io/duration_units.hpp:136:91: error: invalid static_cast from type ‘boost::chrono::duration<boost::rational<int> >::rep {aka boost::rational<int>}’ to type ‘intmax_t {aka long int}’
         return do_get_n_d_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count()));
                                                                                           ^
make: *** [src/chrono_rational.o] Error 1

}}}

Attachments (1)

chrono_rational.tgz (632 bytes ) - added by Sébastien Barthélémy <barthelemy@…> 8 years ago.
unbuildable example

Download all attachments as: .zip

Change History (11)

by Sébastien Barthélémy <barthelemy@…>, 8 years ago

Attachment: chrono_rational.tgz added

unbuildable example

comment:1 by viboes, 8 years ago

Component: Nonechrono
Owner: set to viboes
Status: newassigned

Why do you want the following to compile?

 boost::chrono::duration< boost::rational<int> >

duration expects an integral type.

in reply to:  1 comment:2 by Sébastien Barthélémy <barthelemy@…>, 8 years ago

Hello Vicente,

thank you for your answer.

Replying to viboes:

Why do you want the following to compile?

 boost::chrono::duration< boost::rational<int> >

Well, this specific line does compile, and even the io part did compile under version 1. The compilation only fails with io version 2.

I expected the compilation not to break between versions.

Moreover, the page en.cppreference.com/w/cpp/chrono/duration documents rep as:

Rep, an arithmetic type representing the number of ticks

I'm not sure what "arithmetic type" precisely means in this context, but using a rational type, which supports the arithmetic operations, seemed legit (and does actually work, except for io version 2).

Note that I just discovered this trait class: en.cppreference.com/w/cpp/types/is_arithmetic, maybe there is a precise definition of what an arithmetic type is somewhere in the standard.

Replying to viboes:

duration expects an integral type.

That seems untrue: there is explicit support for floating point numbers.

I guess the crux here is to first understand whether or not std::chrono supports boost::rational-like types as Rep, and then support the same types for the io part.

comment:3 by viboes, 8 years ago

My bad. You are right and std::chrono should support boost::rational.

As you mention Boost.Chrono IO V2 doesn't supports it.

V1 needed just that the Rep supports streaming

    return os << d.count() << ' ' << f.template name<Period>(d.count());

V2 request num_put facet.

        return std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill,
            static_cast<long int> (d.count()));
            //d.count());

When I comment/uncomment the previous lines I got an ambiguous call to put. This was a bug, and when I replace your example by

    typedef boost::chrono::duration< float > RationalSeconds;
    RationalSeconds d(0.5);
    std::cout << d << std::endl;

The decimal part is truncated. I get

0 seconds

instead of

0.5 seconds

I have added a trait that promotes int to long int

    namespace detail
    {
      template <class T>
      struct propagate {
        typedef T type;
      };
      template <>
      struct propagate<boost::int_least32_t> {
        typedef boost::int_least64_t type;
      };
    }

and used it instead of the cast

            static_cast<long int> (d.count()));

as follows

            static_cast<typename detail::propagate<Rep>::type> (d.count()));

This will however not take in account boost::rational as a valid representation.

There are other places where I have added more constraints to the representation.

        return do_get_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count()));

I 'll need to rethink how V2 can take care of IO of Rep not supported by the facets num_get/num_put and many other issues. :(

in reply to:  3 comment:5 by Sébastien Barthélémy <barthelemy@…>, 8 years ago

Vincente,

many thanks for your work on chrono (I should have said that first)

Replying to viboes:

I 'll need to rethink how V2 can take care of IO of Rep not supported by the facets num_get/num_put and many other issues. :(

yes, good luck for that.

Cheers

comment:6 by viboes, 8 years ago

Milestone: To Be DeterminedBoost 1.58.0

You are welcome.

I have found a workaround. While not completely satisfactory from the design point of view, it seems to work.

Please, could you take a look at https://github.com/boostorg/chrono/commit/83b881fad4ecb539c63357c3482c95daf2ca7388

comment:7 by viboes, 8 years ago

While the last commit works for stream inserter (<<), I don't have yet a clear idea on how to take care of stream extractor (>>).

in reply to:  6 comment:8 by Sébastien Barthélémy <barthelemy@…>, 8 years ago

Thank you for the patch

Replying to viboes:

Please, could you take a look at [...]

I commented there.

in reply to:  6 comment:8 by Sébastien Barthélémy <barthelemy@…>, 8 years ago

Replying to viboes:

Please, could you take a look at ..

I commented there. Cheers

comment:9 by viboes, 8 years ago

Resolution: fixed
Status: assignedclosed

I will close this issue, even if the design is not clean.

Note: See TracTickets for help on using tickets.