Opened 11 years ago

Last modified 11 years ago

#6554 new Bugs

Compiler error dereferencing multi_array value via an iterator

Reported by: Bill Buklis Owned by: Ronald Garcia
Milestone: To Be Determined Component: multi_array
Version: Boost 1.49.0 Severity: Problem
Keywords: Cc:

Description

It is currently impossible to dereference/access the values contained in a multi_array via the -> operator from an iterator to the multi_array element. However, use the * operator works.

Example:

struct data
{
	int	value;
};
typedef boost::multi_array<data, 2> array_type;

array_type	a(boost::extents[4][5]);

// ERROR: Cannot compile this line
a.begin()->begin()->value = 7;

// Compiles successfully
(*a.begin()->begin()).value = 5;

I'm using Visual Studio 2010. This is an error in both debug and release modes. This is the error:

boost/multi_array/iterator.hpp(40): error C2528: '->' : pointer to reference is illegal

Attachments (1)

iterator.hpp (5.2 KB ) - added by Bill Buklis 11 years ago.
Merge with trunk version

Download all attachments as: .zip

Change History (2)

comment:1 by Bill Buklis, 11 years ago

I've figured out what the problem is:

I'm not really sure why (perhaps for MWCW and BCC compatibility?), but operator-> for the iterator uses an indirect struct "operator_arrow_proxy" which takes a reference as the type. The operator_arrow_proxy struct then goes on to use a return type for operator-> that is T*. Since T is a reference and not a normal value_type, this is illegal, just as int&* is an illegal type. I modified the structure so that it properly returns a pointer.

Old version:

template <class T>
struct operator_arrow_proxy
{
  operator_arrow_proxy(T const& px) : value_(px) {}
  T* operator->() const { return &value_; }
  // This function is needed for MWCW and BCC, which won't call operator->
  // again automatically per 13.3.1.2 para 8
  operator T*() const { return &value_; }
  mutable T value_;
};

Updated code:

template <class T>
struct operator_arrow_proxy
{
	typedef typename remove_reference<T>::type* pointer;

  operator_arrow_proxy(T const& px) : value_(px) {}
  pointer operator->() const { return &value_; }
  // This function is needed for MWCW and BCC, which won't call operator->
  // again automatically per 13.3.1.2 para 8
  operator pointer() const { return &value_; }
  mutable T value_;
};

The differences are the typedef for "pointer" using remove_reference and changing the return types from T* to pointer. I also added an include for "boost/type_traits/remove_reference.hpp".

Note: This attached iterator.hpp is modified after the trunk version which includes fixes for the MSVC debug output_iterator issue (see ticket:4874). This fix is not currently in the boost release. So if you use the attached file, then make sure to use the rest of the files from the trunk version. The patch itself does not require the MSVC debug fix and may be applied to the release version.

by Bill Buklis, 11 years ago

Attachment: iterator.hpp added

Merge with trunk version

Note: See TracTickets for help on using tickets.