I want to create a class which hold a vector of unique_ptr of data structures, and be iterable as const pointer to data structure.
I tried this piece of code without success:
#include <iostream>
#include <vector>
#include <memory>
#include <boost/compute/iterator/transform_iterator.hpp>
struct data final {
data(int val) : _value(val) {
}
int value() const {
return _value;
}
private:
int _value;
};
const data* get_value(const std::unique_ptr<data>& item) {
return item.get();
}
struct wrapped {
wrapped(std::vector<std::unique_ptr<data>> &&items) : _items(std::move(items)) {
}
auto begin() const {
return boost::compute::make_transform_iterator(_items.begin(), &get_value);
}
auto end() const {
return boost::compute::make_transform_iterator(_items.end(), &get_value);
}
private:
std::vector<std::unique_ptr<data>> _items;
};
int main() {
std::vector<std::unique_ptr<data>> vec;
vec.emplace_back(std::make_unique<data>(42));
wrapped wvec(std::move(vec));
for(const auto &ptr : wvec) {
std::cout << ptr->value() << std::endl;
}
}
I also tried to use a lambda wrapped in a function for get_value without more success:
std::function<const data*(const std::unique_ptr<data>&)> func = [](const std::unique_ptr<data>& item) -> const data* {
return item.get();
};
// then inside struct wrapped:
auto begin() const {
return boost::compute::make_transform_iterator(_items.begin(), func);
}
auto end() const {
return boost::compute::make_transform_iterator(_items.end(), func);
}
I get same compilation errors on both cases, but I don't understand them much. Why doesn't it compile, and how to correct it so it does?
edit: Adding compilation errors:
In file included from test-transform-iterator.cc:8:
/usr/local/include/boost/compute/iterator/transform_iterator.hpp:177:53: error: no member named 'get_buffer' in 'std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>'
const context &context = super_type::base().get_buffer().get_context();
~~~~~~~~~~~~~~~~~~ ^
/usr/local/include/boost/iterator/iterator_facade.hpp:550:20: note: in instantiation of member function 'boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>, std::__1::function<const data *(const std::__1::unique_ptr<data,
std::__1::default_delete<data> > &)> >::dereference' requested here
return f.dereference();
^
/usr/local/include/boost/iterator/iterator_facade.hpp:656:42: note: in instantiation of function template specialization 'boost::iterators::iterator_core_access::dereference<boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> >
*>, std::__1::function<const data *(const std::__1::unique_ptr<data, std::__1::default_delete<data> > &)> > >' requested here
return iterator_core_access::dereference(this->derived());
^
test-transform-iterator.cc:56:23: note: in instantiation of member function 'boost::iterators::detail::iterator_facade_base<boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>, std::__1::function<const data *(const
std::__1::unique_ptr<data, std::__1::default_delete<data> > &)> >, const data *, std::__1::random_access_iterator_tag, const data *, long, false, false>::operator*' requested here
for(const auto &ptr : wvec) {
^
In file included from test-transform-iterator.cc:8:
/usr/local/include/boost/compute/iterator/transform_iterator.hpp:182:42: error: no viable overloaded operator[] for type 'const std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>'
k << "*output = " << m_transform(super_type::base()[k.lit(0)]) << ";";
^~~~~~~~~~~~~~~~~~ ~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:1512:73: note: candidate function not viable: no known conversion from 'detail::meta_kernel_literal<int>' to 'std::__1::__wrap_iter<const std::__1::unique_ptr<data,
std::__1::default_delete<data> > *>::difference_type' (aka 'long') for 1st argument
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT
^
In file included from test-transform-iterator.cc:8:
In file included from /usr/local/include/boost/compute/iterator/transform_iterator.hpp:20:
In file included from /usr/local/include/boost/compute/functional.hpp:19:
In file included from /usr/local/include/boost/compute/functional/atomic.hpp:15:
In file included from /usr/local/include/boost/compute/function.hpp:33:
/usr/local/include/boost/compute/type_traits/type_name.hpp:98:20: error: implicit instantiation of undefined template 'boost::compute::detail::type_name_trait<const data *>'
return detail::type_name_trait<T>::value();
^
/usr/local/include/boost/compute/detail/meta_kernel.hpp:485:19: note: in instantiation of function template specialization 'boost::compute::type_name<const data *>' requested here
stream << type_name<Type>();
^
/usr/local/include/boost/compute/detail/meta_kernel.hpp:409:19: note: in instantiation of function template specialization 'boost::compute::detail::meta_kernel::type<const data **>' requested here
stream << type<T>() << " " << name;
^
/usr/local/include/boost/compute/detail/meta_kernel.hpp:942:24: note: in instantiation of function template specialization 'boost::compute::detail::meta_kernel::add_arg<const data **>' requested here
size_t index = add_arg<T>(name);
^
/usr/local/include/boost/compute/detail/meta_kernel.hpp:422:16: note: in instantiation of function template specialization 'boost::compute::detail::meta_kernel::add_arg_with_qualifiers<const data **>' requested here
return add_arg_with_qualifiers<T>(address_space_prefix(address_space), name);
^
/usr/local/include/boost/compute/iterator/transform_iterator.hpp:181:31: note: in instantiation of function template specialization 'boost::compute::detail::meta_kernel::add_arg<const data **>' requested here
size_t output_arg = k.add_arg<value_type *>(memory_object::global_memory, "output");
^
/usr/local/include/boost/iterator/iterator_facade.hpp:550:20: note: in instantiation of member function 'boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>, std::__1::function<const data *(const std::__1::unique_ptr<data,
std::__1::default_delete<data> > &)> >::dereference' requested here
return f.dereference();
^
/usr/local/include/boost/iterator/iterator_facade.hpp:656:42: note: in instantiation of function template specialization 'boost::iterators::iterator_core_access::dereference<boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> >
*>, std::__1::function<const data *(const std::__1::unique_ptr<data, std::__1::default_delete<data> > &)> > >' requested here
return iterator_core_access::dereference(this->derived());
^
test-transform-iterator.cc:56:23: note: in instantiation of member function 'boost::iterators::detail::iterator_facade_base<boost::compute::transform_iterator<std::__1::__wrap_iter<const std::__1::unique_ptr<data, std::__1::default_delete<data> > *>, std::__1::function<const data *(const
std::__1::unique_ptr<data, std::__1::default_delete<data> > &)> >, const data *, std::__1::random_access_iterator_tag, const data *, long, false, false>::operator*' requested here
for(const auto &ptr : wvec) {
^
/usr/local/include/boost/compute/type_traits/type_name.hpp:24:8: note: template is declared here
struct type_name_trait;
^
3 errors generated.
Boost.Compute is based on OpenCL, and probably not what you want.
Instead, use the Boost.Iterator library:
#include <boost/iterator/transform_iterator.hpp>
boost::make_transform_iterator(_items.begin(), &get_value);