3

I'm trying to extract a const pointer to part way through an array. I found it works fine when using a vector, but won't compile (VS 2008) when using a valarray. Can somebody explain what the problem is?

struct vector_test
{
    std::vector<int> v;

    const int *pointy(const int i) const
    {
        return &(v[i]); // Ok
    }
};

struct valarray_test
{
    std::valarray<int> v;

    const int *pointy(const int i) const
    {
        return &(v[i]); // error C2102: '&' requires l-value
    }
};
manlio
  • 18,345
  • 14
  • 76
  • 126
wxffles
  • 864
  • 6
  • 20
  • 1
    Both usages are violations of the vector or valarray ecapsulation. – Chang Peng May 20 '11 at 00:26
  • @Charles Peng: the first one is technically ok. Vectors explicitely guarantee contiguous storage for compatibility with C-style arrays. Also, the standard defines exactly (a) that the vector's iterator maybe implemented as the pointer to the element type (b) when a vector's iterators are invalidated (e.g. at resizing) – sehe May 20 '11 at 20:57
  • @sehe: Thanks for your comment. I know that the first usage is OK. But what I want to say is that it violates the purpose of encapsulation. – Chang Peng May 21 '11 at 06:27
  • Ok. I get your point. I would agree, but it should be noted that it depends on what you use the vector for, in the end. You can use it as modular container, or just as an 'dynamic array shell' with stack semantics. The standard does support both usage scenarios explicitly. – sehe May 21 '11 at 09:33
  • 2
    @Charles Peng: Unfortunately many code like BLAS/LAPACK does not support valarray. They only support pointers. – xis Jul 30 '11 at 20:43

1 Answers1

12

std::valarray<T>::operator [](std::size_t) returns a T&, which will work fine.

std::valarray<T>::operator [](std::size_t) const returns a T, which will be an rvalue and consequently cannot have its address taken.

Because valarray_test::pointy is itself const, valarray_test::v is treated as const and consequently the const overload of operator[] is called. Either make valarray_test::v mutable or make valarray_test::pointy non-const.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • That makes sense. Is it assumed that a `valarray` is only going to be used for simple types which can be efficiently returned as a copy? Is there a good reason why `valarray` couldn't have been designed to return a reference? – wxffles May 20 '11 at 01:34
  • 2
    "*Is it assumed that a `valarray` is only going to be used for simple types which can be efficiently returned as a copy?*" Yes indeed. "*Is there a good reason why `valarray` couldn't have been designed to return a reference?*" Not with modern compilers, but it may have been a provable optimization at the time `valarray` was originally designed (`valarray` was explicitly designed for balls-out efficiency). – ildjarn May 20 '11 at 01:37
  • More importantly: _The `valarray` classes are defined to be free of certain forms of aliasing, thus allowing operations on these classes to be optimized._ (quoted from the C++ standard draft N3485, 26.6.1/2) – musiphil Mar 27 '13 at 07:37