简体   繁体   中英

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> ?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM