Vlad from Moscow
Vlad from Moscow

Reputation: 310950

Is it a bug of the implementation of std::valarray in gcc?

I tried the following program

#include <iostream>
#include <valarray>

int main( void ) 
{
    std::valarray<int> v1 = { 1, 2, 3, 4, 5 };
    std::valarray<int> v2 = { 1, 2, 3, 4, 5 };

    auto v3 = v1 * v2;

    for ( const auto &item : v3 ) std::cout << item << ' ';
    std::cout << '\n';

    return 0;
}

and got an error message that an appropriate function begin for v3 used implicitly in this statement

    for ( const auto &item : v3 ) std::cout << item << ' ';

can not be found.

So I tried the following code

#include <iostream>
#include <valarray>
#include <type_traits>

int main( void ) 
{
    std::valarray<int> v1 = { 1, 2, 3, 4, 5 };
    std::valarray<int> v2 = { 1, 2, 3, 4, 5 };

    auto v3 = v1 * v2;

    std::cout << std::is_same<std::valarray<int>, decltype( v3 )>::value << '\n';
    return 0;
}

and got the result

0

But when this statement

auto v3 = v1 * v2;

is changed to

std::valarray<int> v3 = v1 * v2;

then the output is

1

The operator * for std::valarray<int> is declared the following way

template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&);

So is it a bug of the implementation of std::valarray<int>?

Upvotes: 4

Views: 318

Answers (1)

NathanOliver
NathanOliver

Reputation: 180500

This is not a bug. std::valarray::operator* does not actually have to return a std::valarray because it is allowed to use expression templates. That means it can return a type that has the following properties:

  • All const member functions of std::valarray are provided.
  • std::valarray, std::slice_array, std::gslice_array, std::mask_array and std::indirect_array can be constructed from the replacement type.
  • All functions accepting an argument of type const std::valarray& except begin() and end() (since C++11) should also accept the replacement type.
  • All functions accepting two arguments of type const std::valarray& should accept every combination of const std::valarray& and the replacement type.
  • The return type does not add more than two levels of template nesting over the most deeply-nested argument type.

emphasis mine source

Because of this, you need to explicitly capture the return as a std::valarray so the specialization for std::begin can be called.

Upvotes: 5

Related Questions