I'm trying to create and return a boost:any_range that contains only one object (I don't know if that's the core problem) but I get the following errors:
- error C2893: Failed to specialize function template 'range_iterator<C,void>::type boost::range_adl_barrier::begin(T &)'
- note: With the following template arguments:
- note: 'T=const WrappedRange'
- error C2672: 'end': no matching overloaded function found
- error C2893: Failed to specialize function template
'range_iterator<C,void>::type boost::range_adl_barrier::end(T &)' - note: With the following template arguments: note: 'T=const
WrappedRange'
Below you can find the relevant code snippets:
- That's the function I want to call and which fails during compiling:
const HandleRange BasicCollection::GetPartHandles() const
{
return HandleRange
//return -> also tried this
{
Handle(GenericHandleManager::CreatePartHandleValue(GenericHandleManager::GetPartIdx(_collectionHandle)))
};
}
Somehow this works, but that's not really clean:
const HandleRange BasicCollection::GetPartHandles() const
{
auto container = { _collectionHandle };
return container | boost::adaptors::transformed([collectionHandle = _collectionHandle](const auto & index_value)
{
return HandleRange::value_type
{
Handle(GenericHandleManager::CreatePartHandleValue(GenericHandleManager::GetPartIdx(collectionHandle)))
};
});
}
- That's the HandleRange type that shall be returned:
/**
* Defines an alias representing a boost range for handles.
*/
using HandleRange = boost::any_range<Handle, boost::forward_traversal_tag, const Handle>;
- The used Handle object:
class Handle
{
public:
/**
* Construct a handle from a handle value.
* @param value The handle's value.
*/
inline explicit Handle(int_fast64_t value) noexcept : _value(value)
{
}
...
}
Thanks for any suggestions!
That should not compile without diagnostics, as
auto
is deduced asstd::initializer_list<Handle>
.That approach invokes Undefined Behaviour because the initializer list doesn't exist after returning.
Solutions
The
any_range
should be able to return an iterator range.Pointers are iterators.
Any single object
o
can be seen as a range[&o, &o + 1)
. That's a valid iterator range.Combining these would already be a solution if
GenericHandleManager::CreatePartHandleValue(...)
returns a reference:Singleton Ranges
If it returns a temporary, though, you'll need to make that "a range":
Now you can safely¹ write (even though
CreatePartHandleValue
returns a temporary):Full Demo
Live On Coliru
Prints
¹ as long as you make sure you don't use any iterators from the SingletonRange after the lifetime of the range. This is a common C++ pattern though