c++boostc++17boost-iterators

use make_transform_iterator on vector of std::unique_ptr to get const pointer


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.

Solution

  • 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);