1
#include <valarray>  
#include<iostream> 

typedef std::valarray<int>    valarray_t;
typedef std::valarray<bool>   maskarray_t;

int main(void) {

  valarray_t::value_type   ibuf[10] = {0,1,2,3,4,5,6,7,8,9};
  valarray_t               vi1(ibuf, 10);
  valarray_t               vi2(ibuf, 10);
  

  // Create a valarray of bools for a mask.
  maskarray_t::value_type  mbuf[10] = {0,1,0,1,1,0,1,0,1,1};
  maskarray_t              mask(mbuf,10);
  
  maskarray_t::value_type  mbuf2[10] = {0,1,1,1,1,1,1,0,0,0};
  maskarray_t              mask2(mbuf2,10);
  
  // test 1:
   vi1[mask] = static_cast<valarray_t> (vi1[mask2]);
   std::cout << "vi1[mask] = vi1[mask2]\n\n" << vi1[0] <<'\t'<<vi1[1]<<'\t' <<vi1[2]<<'\t'<<vi1[3]<<'\t'<<vi1[4]<<'\t'<<vi1[5]<<'\t'<<vi1[6]<<'\t'<<vi1[7]<<'\t'<<vi1[8]<<'\t'<<vi1[9]<<'\t'<< std::endl;

    //test2: 
    std::cout<<"**********************test result=result2"<<std::endl;
    std::mask_array<int>    result1= vi2[mask];
    std::mask_array<int>    result2 = vi2[mask2];

    std::valarray<int>      temp1(result1);
    
    std::cout<<"temp1[0]="<<temp1[0]<<" temp1[1]="<<temp1[1]<<" temp1[2]="<<temp1[2]<<" temp1[3]="<<temp1[3]<<std::endl;
     
     result1=result2;

    std::valarray<int>      temp2(result1);
    std::cout<<"temp2[0]="<<temp2[0]<<" temp2[1]="<<temp2[1]<<" temp2[2]="<<temp2[2]<<" temp2[3]="<<temp2[3]<<std::endl;
     
     
     result1=result2;
     std::cout << "result1= result2\n" << vi2[0] <<'\t'<<vi2[1]<<'\t' <<vi2[2]<<'\t'<<vi2[3]<<'\t'<<vi2[4]<<'\t'<<vi2[5]<<'\t'<<vi2[6]<<'\t'<<vi2[7]<<'\t'<<vi2[8]<<'\t'<<vi2[9]<<'\t'<< std::endl;
     
  return 0;
}

Testing the code above, I got

vi1[mask] = vi1[mask2]

0   1   2   2   3   5   4   7   5   6   

**********************test result=result2

temp1[0]=1  temp1[1]=3 temp1[2]=4 temp1[3]=6

temp2[0]=1  temp2[1]=3 temp2[2]=4 temp2[3]=6

result1= result2

0   1   2   3   4   5   6   7   8   9

For my understanding, both of the results are wrong.

orig:     0 1 2 3 4 5 6 7 8 9 
mask:       ^   ^ ^   ^   ^ ^
mask2:      ^ ^ ^ ^ ^ ^ 
vi1[mask]=vi1[mask2] or result1=result2
          0 1 2 2 2 5 2 7 5 2   

orig[3]=orig[2] //orig[2] is 2, so orig[3] is 2

orig[4]=orig[3] //orig[3] is set to 2 from last step, so orig[4] is set to 2.

...

So my questions are:

  1. why do I get different outputs from test1 and test2? Should test1 and test2 give the same result?
  2. Are both outputs wrong? if not, why?
  3. For test2, the original array doesn't seem to be updated. Why? Is it a bug?

I used a pretty old compiler and llvm c++ library, try to figure out if it is a bug or I understand/use mask_array wrong.

Please kindly share your thoughts. Thanks for any comments.

cigien
  • 57,834
  • 11
  • 73
  • 112
issac
  • 155
  • 8
  • LOL! I get a linker error when building this code in Visual Studio 2019 (16.7.3) `unresolved external symbol "public: class std::mask_array & __thiscall std::mask_array::operator=(class std::mask_array const &)"`. Going to the code with 'find definition' shows the comment "// not defined" xD – JHBonarius Sep 11 '20 at 18:14
  • Ah it was already fixed in the [source](https://github.com/microsoft/STL/blob/9e76d8c3d3700e086f3fbedd0c5b71f1678e4796/stl/inc/valarray#L1809). – JHBonarius Sep 11 '20 at 18:45
  • I'm guessing it's a compiler/implementation error. With both msvc (fixed) and g++ I get different your 'correct' output. I have no idea what's happening under the hood by the way. – JHBonarius Sep 11 '20 at 18:51
  • Thanks for your attention, JHBonarius. I also suspected that it is a bug. – issac Sep 11 '20 at 20:25
  • Is the order of element assignments guaranteed by the standard? On cplusplus.com/reference under "complexity" it says "operations may be parallelized", which makes me think order of assignment is probably not guaranteed, but I'm not sure one way or the other. – Darryl Sep 11 '20 at 21:16

0 Answers0