Posts Tagged slice_array

Fussing with slice_array

Some times we just make things far to complicated for ourselves: note to self (and whoever cares),do not put compiler hints into unproven code. Every now and then you overstep your confidence and do something that you look back at and think, “Now that’s just stupid!”. I’ve just spent the last several days wondering why the following does not compile.

void foo( const std::valarray<int> & va ) {
  std::slice_array<int> sa = va[std::slice( 1, 1, 1 )];
}

After all the line in the middle is exactly the same as sooo much example code out there it isn’t funny. However the compiler throws an awful wobbly and kicks back an error like this.

example.cc: In function ‘void foo(const std::valarray<int>&)’:
example.cc:20: error:
    conversion from
        ‘std::_Expr<std::_SClos<std::_ValArray, int>, int>’
    to non-scalar type
        ‘std::slice_array<int>’
    requested

Which is not quite what I expected. I’ve laid it out a bit different to the compiler for readability. Essentially the error means that the type of the expression on the right is not equivalent to the type of the variable on the left. However you can do this.

void foo( const std::valarray<int> & va ) {
  std::valarray<int> sa = va[std::slice( 1, 1, 1 )];
}

Which of course will compile without issue. OK so the operator() is overloaded, what’s its problem? The solution is blindingly obvious, but for those with a sense of anticipation I’ll drag it out just a tiny wee bit more. The mystery, and partly where I went wrong, was deepened by the valarray header.

/**
*  @brief  Return an array subset.
*
*  Returns a new valarray containing the elements of the array
*  indicated by the slice argument.  The new valarray has the same size
*  as the input slice.  @see slice.
*
*  @param  s  The source slice.
*  @return  New valarray containing elements in @a s.
*/
_Expr<_SClos<_ValArray, _Tp>, _Tp> operator[](slice) const;

/**
* @brief Return a reference to an array subset.
*
* Returns a new valarray containing the elements of the array
* indicated by the slice argument. The new valarray has the same size
* as the input slice. @see slice.
*
* @param s The source slice.
* @return New valarray containing elements in @a s.
*/
slice_array<_Tp> operator[](slice);

Now that's probably give it away if you didn't already know. But once again I wasn't looking properly. There were two real problems and none of them to do with my code: firstly I was programming by Google, secondly I was trying to be smart. The first error was as stupid as a cut and paste error. I'd looked up similar issues in Google and cut someone else's understanding of the problem out of a page that I had read and stapled it into my brain. Seems someone else had the same problem but not the nouse to get over it and was blaming the spec. Very silly, I should have known better. The second thing was that I'd tried to hint to the compiler before understanding its implications. Never hint to the compiler before you have the thing working, I'd have never wasted my time with it, although programming by debugger has its own worms.

Turns out this is the code that I wanted.

void foo( std::valarray<int> & va ) {
  std::slice_array<int> sa = va[std::slice( 1, 1, 1 )];
}

See it? If you still can't see it compare it to the earlier version and have a look at the prototypes in copied from the header above, which should explain almost everything. All that time. Silly, silly silly ... proceed with self flagellation of 50 lashings with a wet noodle! I have 15 years experience programming with C++ and 20 with C (which can generate similar errors), very embarrassing.

, ,

No Comments