boostorg / boostorg/compute

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

Open
#897 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
1.7k
Forks
340
PR merge metrics
No merged PRs in 30d

Description

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

using namespace boost::compute;

int f(constant_iterator 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::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>' 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, 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
35 class constant_iterator_base
36 {
37 public:
38 typedef ::boost::iterator_facade<
39 ::boost::compute::constant_iterator,
40 T,
41 ::std::random_access_iterator_tag
42 > type;
43 };
..
59 template
60 class constant_iterator : public detail::constant_iterator_base::type
61 {
..
63 typedef typename detail::constant_iterator_base::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
35 class constant_iterator_base
36 {
37 public:
38 typedef ::boost::iterator_facade<
39 ::boost::compute::constant_iterator,
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](https://github.com/boostorg/compute/blob/boost-1.90.0/test/test_constant_iterator.cpp) fails to exercise the iterator dereference operation, presumably due to `boost::compute::copy()` using a different operation such as `operator[]`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.