Skip to content

constant_iterator and counting_iterator dereference attempts to bind a const object to a reference #897

@tahonermann

Description

@tahonermann

The following test case illustrates a compilation failure that occurs when attempting to dereference an instance of constant_iterator instantiated for a non-const value type.

#include <boost/compute/iterator/constant_iterator.hpp>

using namespace boost::compute;

int f(constant_iterator<int> ci) {
  return *ci;
}

When compiled by the Intel oneAPI compiler (a fork of Clang), the following error (demonstrated using the oneAPI icx driver on Windows) is produced:

$ icx /c /I../tmp/boost_1_90_0 /EHsc -std:c++20 t.cpp
...
In file included from ...\t.cpp:1:
...\boost_1_90_0\boost\compute\iterator\constant_iterator.hpp(113,16): error:
      binding reference of type 'int' to value of type 'const int' drops 'const' qualifier
  113 |         return m_value;
      |                ^~~~~~~
...\boost_1_90_0\boost\iterator\iterator_facade.hpp(500,18): note: in instantiation
      of member function 'boost::compute::constant_iterator<int>::dereference' requested here
  500 |         return f.dereference();
      |                  ^
...\boost_1_90_0\boost\iterator\iterator_facade.hpp(598,38): note: in instantiation
      of function template specialization
      'boost::iterators::iterator_core_access::dereference<boost::compute::constant_iterator<int>>' requested here
  598 |         return iterator_core_access::dereference(this->derived());
      |                                      ^
...\t.cpp(6,10): note: in instantiation of member function
      'boost::iterators::detail::iterator_facade_base<boost::compute::constant_iterator<int>, int,
      std::random_access_iterator_tag, int &, long long, false, false>::operator*' requested here
    6 |   return *ci;
      |          ^
1 error generated.

The relevant code from the constant_iterator.hpp header file is excerpted below (From https://github.com/boostorg/compute/blob/boost-1.90.0/include/boost/compute/iterator/constant_iterator.hpp):

 34 template<class T>
 35 class constant_iterator_base
 36 {
 37 public:
 38     typedef ::boost::iterator_facade<
 39         ::boost::compute::constant_iterator<T>,
 40         T,
 41         ::std::random_access_iterator_tag
 42     > type;
 43 };
 ..
 59 template<class T>
 60 class constant_iterator : public detail::constant_iterator_base<T>::type
 61 {
 ..
 63     typedef typename detail::constant_iterator_base<T>::type super_type;
 64     typedef typename super_type::reference reference;
 ..
111     reference dereference() const
112     {
113         return m_value;
114     }
...
147     T m_value;
...
149 };

Iterator dereference for constant_iterator is implemented by the dereference() member. The problem is that reference is defined as T&. When T is a non-const type, then reference is a reference to a non-const type and the attempt to bind m_value in the return statement fails because dereference() is a const member function and m_value is therefore const-qualified when accessed within its definition.

This issue can probably be fixed in the definition of constant_iterator_base by passing an appropriately const-qualified type as the argument for the Reference template parameter of iterator_facade. For example:

 34 template<class T>
 35 class constant_iterator_base
 36 {
 37 public:
 38     typedef ::boost::iterator_facade<
 39         ::boost::compute::constant_iterator<T>,
 40         T,
-41         ::std::random_access_iterator_tag
+++         ::std::random_access_iterator_tag,
+++         const T&
 42     > type;
 43 };

It seems the test_constant_iterator.cpp test fails to exercise the iterator dereference operation, presumably due to boost::compute::copy() using a different operation such as operator[].

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions