Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#5455 closed Bugs (wontfix)

std::vector<byte_> not assignable to std::vector<unsigned char>

Reported by: jaredgrubb@… Owned by: Hartmut Kaiser
Milestone: To Be Determined Component: spirit
Version: Boost 1.44.0 Severity: Problem
Keywords: Cc:

Description

Using a rule that is like this:

rule = (*qi::byte_) [at_c<0>(_val) = _1];

where _val is a fusion-adapted struct that has a member (std::vector<uint8_t>, data).

I get an error that there is no viable overload of operator= for:

BOOST_BINARY_RESULT_OF(x = y, result_of_assign)

where x = std::vector<unsigned char, std::allocator<unsigned char> > and y = std::vector<boost::integer::endian<2, unsigned char, 8, 0>, std::allocator<boost::integer::endian<2, unsigned char, 8, 0> > >

appears to occur in this instantiation:

boost::phoenix::result_of_assign<std::vector<unsigned char, std::allocator<unsigned char> > &, std::vector<boost::integer::endian<2, unsigned char, 8, 0>, std::allocator<boost::integer::endian<2, unsigned char, 8, 0> > > &>

Change History (7)

comment:1 by Joel de Guzman, 12 years ago

Why is this a bug? Please provide a minimal cpp file I can try. Also see Spirit support: http://boost-spirit.com/home/feedback-and-support/

comment:2 by jaredgrubb@…, 12 years ago

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/adapted/struct/define_struct.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <vector>

BOOST_FUSION_DEFINE_STRUCT( (), Vector, (std::vector<unsigned char>, v))
BOOST_FUSION_DEFINE_STRUCT( (), Byte,   (unsigned char, b))

int main(int argc, char * argv[])
{
    using namespace boost::spirit::qi;
    using namespace boost::phoenix;

    /* r1 compiles fine: byte_ assigns to unsigned char */
    rule<char const *, Byte()> r1;
    r1 = byte_ [at_c<0>(_val)=_1];

    /* r2 does not compile: vector<byte_> does not assign to vector<unsigned char> */
    rule<char const *, Vector()> r2;
    r2 = (*byte_) [at_c<0>(_val)=_1];

    return 0;
}

comment:3 by Joel de Guzman, 12 years ago

Owner: changed from Joel de Guzman to Hartmut Kaiser

Doesn't look like a bug to me. It's the same as trying to assign a vector<boost::integer::endian<2, unsigned char, 8, 0> > from a vector<unsigned char>.

I'll forward to Hartmut Kaiser anyway. He's the author of the binary parsers.

comment:4 by Hartmut Kaiser, 12 years ago

Joel is right, it just can't work the way you set it up. And there is no way for Spirit to figure out how to convert the two vectors. But why do you need to use semantic actions? If you were relying on Spirit's attribute propagation it would be possible to make it work:

r2 = (*byte_) >> eps;

compiles just fine and does what you expect.

comment:5 by Hartmut Kaiser, 12 years ago

Resolution: wontfix
Status: newclosed

comment:6 by jaredgrubb@…, 12 years ago

It just seems odd that all these work:

    U = T
    U %= T
    std::vector<U> %= (*T)
    at_c<n>(U) = T 

but this fails:

    at_c<n>(std::vector<U>) = std::vector<T> 

I was able to work around the issue by using phx::assign, but it just seems inconsistent, especially since there doesnt appear to be any useful way to combine at_c with a vector of byte_'s (std::vector<boost::integer::endian<2, unsigned char, 8, 0> just doesnt seem to be the right way to do it, and it looks like that should be convertible to std::vector<unsigned char>). But, if it's "wontfix", I'll let it go. Thanks.

comment:7 by Joel de Guzman, 12 years ago

That std::vector<U> cannot be assigned to std::vector<T> is not the problem of Spirit but is the problem of the C++ standard library -which is beyond the scope of what we can do. I suggest what Hartmut mentioned: use attribute propagation. There, we have more control of what we can do for ease of use.

Note: See TracTickets for help on using tickets.