Question

Let's try to create a pointer-like type matching both the RandomAccessIterator and the NullablePointer concepts. The goal here is to create a custom Allocator in order to use the std::vector with a our pointer-like type. You can found the snippet here

The problem arises when trying to compile this code :

int main()
{
     std::vector<float, allocator<float>> t {0.f, 0.f};
}

We get the following error message :

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:173:6: error: 
  value of type 'pointer' (aka 'ptr_like<int>') is not contextually convertible
  to 'bool'
    if (__p)

Here we see that our type must be bool convertible. That's not hard to do, and if people have an instance of our pointer type, they're likely going to use it like this anyway. Thus let's do it and uncomment the following to our snippet :

// In detail::ptr_like we add :
operator bool() const;

And we get the following error with clang :

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:168:25: error: 
  conditional expression is ambiguous; 'pointer' (aka 'ptr_like<int>') can be
  converted to 'int' and vice versa
  { return __n != 0 ? _M_impl.allocate(__n) : 0; }

Clang's error shows us exactly why we get into trouble here. Now the only viable solutions that I've found are the following :

  • Replacing 0 with the c++11 keyword nullptr when c++11 is requested
  • Replacing 0 by a cast to the pointer type static_cast<pointer>(0)
  • Updating the concept requirement for pointer in the Allocator concept.
  • No using the constructor with std::initializer_list (sad)

Is it wrong to defines custom pointers in C++ ?

Is it a bug ?

Was it helpful?

Solution

Expanding on my comment.

{ return __n != 0 ? _M_impl.allocate(__n) : 0; }

The first result can convert to bool to int. The second result can convert to int. This is just as good a result as converting the second result to pointer, so it is ambiguous.

But we don't want the bool conversion to be available here, so we can make it explicit. It will still be available in logical conditions and the like, as I describe here. Being contextually convertable to bool is another condition The Standard places on custom pointer types satisfying the NullablePointer requirements (since 2011 - see 17.6.3.3/3).

OTHER TIPS

I suggest to define the conversion operator as explicit. For example

explicit operator bool() const;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top