I was trying to copy some LoanedSamples I had into "non-loaned" dds::sub::Samples. From the documentation, I would expect that I can always convert an rti::sub::LoanedSample<T> into an equivalent dds::sub::Sample<T>. However, it turns out that the constructor, Sample<T>::Sample(const rti::sub::LoanedSample<T>&), does not check whether the LoanedSample is valid or not, and simply tries to access the data() field. From include/ndds/hpp/rti/sub/SampleImpl.hpp:
SampleImpl(const SampleImpl& other) : data_(other.data()), info_(other.info()) { }
I cannot really think of a valid reason why it should behave like this; at the very least there needs to be a big warning in the documentation that you cannot use this constructor on invalid samples.
Now, I can of course build invalid Sample<T> objects without any problem. In fact the default constructor does just that, it constructs an invalid sample. And that brings me to another issue: when calling Sample<T>::data() on an invalid sample, it does not throw an exception, but lets you access the (usually default-constructed) data without complaining.
I would say that the first issue – the exception when constructing from an invalid LoanedSample – is definitely a bug. The second issue – accessing data() on an invalid LoanedSample() without an exception – might not qualify as a bug, it could be intended behavior. But in that case I would expect the documentation to make me aware of this.
Are these differences between LoanedSample and Sample a bug, an oversight, or a slightly underdocumented feature?
This is with RTI Connext 5.2.0. Do newer versions differ in this regard?
Thanks for any information.
Hi,
I agree with your comments. Sample has both an inconsitent and underdocumented behavior. I have filed a bug to fix the constructor and not throw an exception when creating a Sample from a LoanedSample with invalid data (reference: CORE-8446) and a documentation bug to clarify how Sample::data() should work (reference: CORE-8447).
I'm not sure how you're copying LoanedSamples into Samples, but if you want to skip invalid-data samples, you can use the iterator adapter rti::sub::valid_samples. For example, given a LoanedSamples container 'samples' and a destination 'data_vector' (can be a std::vector<Foo> or std::vector<Sample<Foo>>) :
I hope this helps,
Alex Campos
Principal Software Engineer, RTI
Alex,
thanks very much for your help! In my use case, I want to convert all samples, valid or not, from Loaned to non-Loaned. I use a small helper function:
Copying a whole set of samples is done with a simple range-based for loop: