You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Kim van der Riet <ki...@redhat.com> on 2018/03/28 14:45:41 UTC

[C++ binding] Complex types: defining an array of arrays of differing types

By default, using std::vector<c++-type> is encoded as an AMQP array, 
whereas std::vector<proton::value> is encoded as an AMQP list. So, to 
create an array of lists of differing types, for example:

std::vector<proton::value> list1 = {uint8_t(0), uint8_t(1)};
std::vector<proton::value> list2 = {true, false};
std::vector<std::vector<proton::value> > array = {list1, list2};

works ok. However, how does one define an array of arrays of differing 
types? For example:

std::vector<uint8_t> array1 = {uint8_t(0), uint8_t(1)};
std::vector<bool> array2 = {true, false};
std::vector<std::vector<##> > array3 = {array1, array2};

What is ##? Unless all the sub-arrays are of the same type, it is not 
possible to define a single type here. If I use proton::value (which 
would make it indistinguishable from the array of lists above), I get a 
compile error:

could not convert '{array1, array2}' from '<brace-enclosed initializer 
list' to 'std::vector<std::vector<proton::value> >'

What is the correct way to create an array of arrays of differing types?

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Re: [C++ binding] Complex types: defining an array of arrays of differing types

Posted by Kim van der Riet <ki...@redhat.com>.
Hi Chris,

Thanks for the great suggestions. These are great solutions at a pure 
C++ level. I need to wait for the Proton folks to weigh in on what the 
Proton encoder can/will do. I don't think it will know what to do with a 
boost::variant. That part of the source is rather hard to penetrate (for 
me, at least!)

Kim


On 03/28/2018 12:59 PM, Chris Richardson wrote:
> Is using boost::variant an option? Then you could use something like
> 
>    #include <boost/variant.hpp>
> ...
> 
>    typedef boost::variant<uint8_t, bool> elem_type;
> 
>    std::vector<elem_type> array1 = {uint8_t(0), uint8_t(1)};
>    std::vector<elem_type> array2 = {true, false};
> 
>    std::vector<std::vector<elem_type>> array3 = {array1, array2};
> 
> This at least compiles, but I don't know if it will produce the results you
> want from a QITS perspective.
> 
> Chris
> 
> On 28 March 2018 at 17:23, Kim van der Riet <ki...@redhat.com> wrote:
> 
>> This is part of the Qpid Interop Test Suite, a test written for complex
>> type interoperability.
>>
>> AMQP allows arrays of arrays of differing types, I am wanting to test this
>> using the different bindings against each other - this is what the QITS
>> does.
>>
>> In the case of the C++ binding, the default encoding for an AMQP array
>> occurs when a container (std::vector, std::deque, etc.) is of a c++ type
>> rather than using proton::value, which would cause the encoding to be an
>> AMQP list.
>>
>> Certainly I can see that the non-homogenous nature of the declaration is
>> the issue, I just don't know how to get around it in a way that the Proton
>> encoder will accept. I know there is a way to force a
>> std::vector<proton::value> to be encoded as an array, but I don't know how
>> to do that.
>>
>> Kim
>>
>>
>> On 03/28/2018 11:49 AM, Chris Richardson wrote:
>>
>>> The short answer is "you can't", at least not along the lines you're
>>> thinking. The std::vector type is a homogeneous container, see eg: this
>>> for
>>> more info: https://isocpp.org/wiki/faq/containers#heterogeneous-contain
>>> ers
>>>
>>> The upshot is that the elements of the vectors must have a common (base)
>>> type, which clearly uint8_t and bool do not. The usual way to get around
>>> this is exactly as you've outlined - to use some sort of variant-style
>>> container such as the proton::value or boost::variant etc. The
>>> alternatives
>>> (as mentioned in the above article) are almost too terrible to contemplate
>>> and would involve lists of void pointers and risky reinterpret_casts
>>> scattered through the code <shudder>.
>>>
>>> In some situations it can be useful to use a tuple type, then you could
>>> have some construct like
>>> std::tuple<std::vector<uint8_t>, std::vector<bool>>
>>> but if your list isn't of a fixed size known at compile-time (or
>>> specifically needs to be a vector) this probably isn't what you're after
>>> either.
>>>
>>> Can you say more about what you're trying to do and why proton::value
>>> isn't
>>> sufficient?
>>>
>>> Chris
>>>
>>>
>>>
>>> On 28 March 2018 at 15:45, Kim van der Riet <ki...@redhat.com>
>>> wrote:
>>>
>>> By default, using std::vector<c++-type> is encoded as an AMQP array,
>>>> whereas std::vector<proton::value> is encoded as an AMQP list. So, to
>>>> create an array of lists of differing types, for example:
>>>>
>>>> std::vector<proton::value> list1 = {uint8_t(0), uint8_t(1)};
>>>> std::vector<proton::value> list2 = {true, false};
>>>> std::vector<std::vector<proton::value> > array = {list1, list2};
>>>>
>>>> works ok. However, how does one define an array of arrays of differing
>>>> types? For example:
>>>>
>>>> std::vector<uint8_t> array1 = {uint8_t(0), uint8_t(1)};
>>>> std::vector<bool> array2 = {true, false};
>>>> std::vector<std::vector<##> > array3 = {array1, array2};
>>>>
>>>> What is ##? Unless all the sub-arrays are of the same type, it is not
>>>> possible to define a single type here. If I use proton::value (which
>>>> would
>>>> make it indistinguishable from the array of lists above), I get a compile
>>>> error:
>>>>
>>>> could not convert '{array1, array2}' from '<brace-enclosed initializer
>>>> list' to 'std::vector<std::vector<proton::value> >'
>>>>
>>>> What is the correct way to create an array of arrays of differing types?
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
>>>> For additional commands, e-mail: users-help@qpid.apache.org
>>>>
>>>>
>>>>
>>>
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
>> For additional commands, e-mail: users-help@qpid.apache.org
>>
>>
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Re: [C++ binding] Complex types: defining an array of arrays of differing types

Posted by Chris Richardson <cr...@fourc.eu>.
Is using boost::variant an option? Then you could use something like

  #include <boost/variant.hpp>
...

  typedef boost::variant<uint8_t, bool> elem_type;

  std::vector<elem_type> array1 = {uint8_t(0), uint8_t(1)};
  std::vector<elem_type> array2 = {true, false};

  std::vector<std::vector<elem_type>> array3 = {array1, array2};

This at least compiles, but I don't know if it will produce the results you
want from a QITS perspective.

Chris

On 28 March 2018 at 17:23, Kim van der Riet <ki...@redhat.com> wrote:

> This is part of the Qpid Interop Test Suite, a test written for complex
> type interoperability.
>
> AMQP allows arrays of arrays of differing types, I am wanting to test this
> using the different bindings against each other - this is what the QITS
> does.
>
> In the case of the C++ binding, the default encoding for an AMQP array
> occurs when a container (std::vector, std::deque, etc.) is of a c++ type
> rather than using proton::value, which would cause the encoding to be an
> AMQP list.
>
> Certainly I can see that the non-homogenous nature of the declaration is
> the issue, I just don't know how to get around it in a way that the Proton
> encoder will accept. I know there is a way to force a
> std::vector<proton::value> to be encoded as an array, but I don't know how
> to do that.
>
> Kim
>
>
> On 03/28/2018 11:49 AM, Chris Richardson wrote:
>
>> The short answer is "you can't", at least not along the lines you're
>> thinking. The std::vector type is a homogeneous container, see eg: this
>> for
>> more info: https://isocpp.org/wiki/faq/containers#heterogeneous-contain
>> ers
>>
>> The upshot is that the elements of the vectors must have a common (base)
>> type, which clearly uint8_t and bool do not. The usual way to get around
>> this is exactly as you've outlined - to use some sort of variant-style
>> container such as the proton::value or boost::variant etc. The
>> alternatives
>> (as mentioned in the above article) are almost too terrible to contemplate
>> and would involve lists of void pointers and risky reinterpret_casts
>> scattered through the code <shudder>.
>>
>> In some situations it can be useful to use a tuple type, then you could
>> have some construct like
>> std::tuple<std::vector<uint8_t>, std::vector<bool>>
>> but if your list isn't of a fixed size known at compile-time (or
>> specifically needs to be a vector) this probably isn't what you're after
>> either.
>>
>> Can you say more about what you're trying to do and why proton::value
>> isn't
>> sufficient?
>>
>> Chris
>>
>>
>>
>> On 28 March 2018 at 15:45, Kim van der Riet <ki...@redhat.com>
>> wrote:
>>
>> By default, using std::vector<c++-type> is encoded as an AMQP array,
>>> whereas std::vector<proton::value> is encoded as an AMQP list. So, to
>>> create an array of lists of differing types, for example:
>>>
>>> std::vector<proton::value> list1 = {uint8_t(0), uint8_t(1)};
>>> std::vector<proton::value> list2 = {true, false};
>>> std::vector<std::vector<proton::value> > array = {list1, list2};
>>>
>>> works ok. However, how does one define an array of arrays of differing
>>> types? For example:
>>>
>>> std::vector<uint8_t> array1 = {uint8_t(0), uint8_t(1)};
>>> std::vector<bool> array2 = {true, false};
>>> std::vector<std::vector<##> > array3 = {array1, array2};
>>>
>>> What is ##? Unless all the sub-arrays are of the same type, it is not
>>> possible to define a single type here. If I use proton::value (which
>>> would
>>> make it indistinguishable from the array of lists above), I get a compile
>>> error:
>>>
>>> could not convert '{array1, array2}' from '<brace-enclosed initializer
>>> list' to 'std::vector<std::vector<proton::value> >'
>>>
>>> What is the correct way to create an array of arrays of differing types?
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
>>> For additional commands, e-mail: users-help@qpid.apache.org
>>>
>>>
>>>
>>
>>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
> For additional commands, e-mail: users-help@qpid.apache.org
>
>


-- 

*Chris Richardson*, System Architect
cr@fourc.eu


*FourC AS, Vestre Rosten 81, Trekanten, NO-7075 Tiller, Norwaywww.fourc.eu
<http://www.fourc.eu/>*

*Follow us on LinkedIn <http://bit.ly/fourcli>, Facebook
<http://bit.ly/fourcfb>, Google+ <http://bit.ly/fourcgp> and Twitter
<http://bit.ly/fourctw>!*

Re: [C++ binding] Complex types: defining an array of arrays of differing types

Posted by Kim van der Riet <ki...@redhat.com>.
This is part of the Qpid Interop Test Suite, a test written for complex 
type interoperability.

AMQP allows arrays of arrays of differing types, I am wanting to test 
this using the different bindings against each other - this is what the 
QITS does.

In the case of the C++ binding, the default encoding for an AMQP array 
occurs when a container (std::vector, std::deque, etc.) is of a c++ type 
rather than using proton::value, which would cause the encoding to be an 
AMQP list.

Certainly I can see that the non-homogenous nature of the declaration is 
the issue, I just don't know how to get around it in a way that the 
Proton encoder will accept. I know there is a way to force a 
std::vector<proton::value> to be encoded as an array, but I don't know 
how to do that.

Kim


On 03/28/2018 11:49 AM, Chris Richardson wrote:
> The short answer is "you can't", at least not along the lines you're
> thinking. The std::vector type is a homogeneous container, see eg: this for
> more info: https://isocpp.org/wiki/faq/containers#heterogeneous-containers
> 
> The upshot is that the elements of the vectors must have a common (base)
> type, which clearly uint8_t and bool do not. The usual way to get around
> this is exactly as you've outlined - to use some sort of variant-style
> container such as the proton::value or boost::variant etc. The alternatives
> (as mentioned in the above article) are almost too terrible to contemplate
> and would involve lists of void pointers and risky reinterpret_casts
> scattered through the code <shudder>.
> 
> In some situations it can be useful to use a tuple type, then you could
> have some construct like
> std::tuple<std::vector<uint8_t>, std::vector<bool>>
> but if your list isn't of a fixed size known at compile-time (or
> specifically needs to be a vector) this probably isn't what you're after
> either.
> 
> Can you say more about what you're trying to do and why proton::value isn't
> sufficient?
> 
> Chris
> 
> 
> 
> On 28 March 2018 at 15:45, Kim van der Riet <ki...@redhat.com> wrote:
> 
>> By default, using std::vector<c++-type> is encoded as an AMQP array,
>> whereas std::vector<proton::value> is encoded as an AMQP list. So, to
>> create an array of lists of differing types, for example:
>>
>> std::vector<proton::value> list1 = {uint8_t(0), uint8_t(1)};
>> std::vector<proton::value> list2 = {true, false};
>> std::vector<std::vector<proton::value> > array = {list1, list2};
>>
>> works ok. However, how does one define an array of arrays of differing
>> types? For example:
>>
>> std::vector<uint8_t> array1 = {uint8_t(0), uint8_t(1)};
>> std::vector<bool> array2 = {true, false};
>> std::vector<std::vector<##> > array3 = {array1, array2};
>>
>> What is ##? Unless all the sub-arrays are of the same type, it is not
>> possible to define a single type here. If I use proton::value (which would
>> make it indistinguishable from the array of lists above), I get a compile
>> error:
>>
>> could not convert '{array1, array2}' from '<brace-enclosed initializer
>> list' to 'std::vector<std::vector<proton::value> >'
>>
>> What is the correct way to create an array of arrays of differing types?
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
>> For additional commands, e-mail: users-help@qpid.apache.org
>>
>>
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Re: [C++ binding] Complex types: defining an array of arrays of differing types

Posted by Chris Richardson <cr...@fourc.eu>.
The short answer is "you can't", at least not along the lines you're
thinking. The std::vector type is a homogeneous container, see eg: this for
more info: https://isocpp.org/wiki/faq/containers#heterogeneous-containers

The upshot is that the elements of the vectors must have a common (base)
type, which clearly uint8_t and bool do not. The usual way to get around
this is exactly as you've outlined - to use some sort of variant-style
container such as the proton::value or boost::variant etc. The alternatives
(as mentioned in the above article) are almost too terrible to contemplate
and would involve lists of void pointers and risky reinterpret_casts
scattered through the code <shudder>.

In some situations it can be useful to use a tuple type, then you could
have some construct like
std::tuple<std::vector<uint8_t>, std::vector<bool>>
but if your list isn't of a fixed size known at compile-time (or
specifically needs to be a vector) this probably isn't what you're after
either.

Can you say more about what you're trying to do and why proton::value isn't
sufficient?

Chris



On 28 March 2018 at 15:45, Kim van der Riet <ki...@redhat.com> wrote:

> By default, using std::vector<c++-type> is encoded as an AMQP array,
> whereas std::vector<proton::value> is encoded as an AMQP list. So, to
> create an array of lists of differing types, for example:
>
> std::vector<proton::value> list1 = {uint8_t(0), uint8_t(1)};
> std::vector<proton::value> list2 = {true, false};
> std::vector<std::vector<proton::value> > array = {list1, list2};
>
> works ok. However, how does one define an array of arrays of differing
> types? For example:
>
> std::vector<uint8_t> array1 = {uint8_t(0), uint8_t(1)};
> std::vector<bool> array2 = {true, false};
> std::vector<std::vector<##> > array3 = {array1, array2};
>
> What is ##? Unless all the sub-arrays are of the same type, it is not
> possible to define a single type here. If I use proton::value (which would
> make it indistinguishable from the array of lists above), I get a compile
> error:
>
> could not convert '{array1, array2}' from '<brace-enclosed initializer
> list' to 'std::vector<std::vector<proton::value> >'
>
> What is the correct way to create an array of arrays of differing types?
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
> For additional commands, e-mail: users-help@qpid.apache.org
>
>


-- 

*Chris Richardson*, System Architect
cr@fourc.eu


*FourC AS, Vestre Rosten 81, Trekanten, NO-7075 Tiller, Norwaywww.fourc.eu
<http://www.fourc.eu/>*

*Follow us on LinkedIn <http://bit.ly/fourcli>, Facebook
<http://bit.ly/fourcfb>, Google+ <http://bit.ly/fourcgp> and Twitter
<http://bit.ly/fourctw>!*