Руководство по удержанию для шаблона класса std :: valarray <T> - PullRequest
0 голосов
/ 08 октября 2019

В стандарте C ++ есть следующее руководство по выводу для класса шаблона std::valarray<T>:

template<class T, size_t cnt> valarray(const T(&)[cnt], size_t) -> valarray<T>;

Однако среди конструкторов класса есть только следующий подходящий конструктор (или я ошибаюсь? )

valarray(const T&, size_t);

Однако, если запустить следующую демонстрационную программу с аналогичным руководством по выводу

#include <iostream>
#include <utility>

template <typename T>
struct A
{
    A( const T &, size_t ) { std::cout << "A<T>()\n"; }
};

template<class T, size_t cnt> 
A(const T(&)[cnt], size_t) -> A<T>;

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    A obj( a, std::size( a ) );
}

, компилятор gcc выдает ошибку

rog.cc:17:12: error: invalid conversion from 'int*' to 'int' [-fpermissive]
   17 |     A obj( a, std::size( a ) );
      |            ^
      |            |
      |            int*
prog.cc:7:8: note:   initializing argument 1 of 'A<T>::A(const T&, size_t) [with T = int; size_t = long unsigned int]'
    7 |     A( const T &, size_t ) { std::cout << "A<T>()\n"; }
      |        ^~~~~~~~~

Таким образом, возникает вопросбудь то дефект стандарта C ++, или ошибка компилятора, или я что-то пропустил.

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Используя пример, заданный https://en.cppreference.com/w/cpp/numeric/valarray/deduction_guides,, мы можем посмотреть на вывод компилятора без оптимизации, чтобы увидеть, какой конструктор вызывается:

int a[] = {1, 2, 3};
std::valarray va(a, 3);

https://godbolt.org/z/rtgeoi

main:
    [...]
    call    std::valarray<int>::valarray(int const*, unsigned long)
    [...]

C ++ массивы распадаются на указатели на их первый элемент очень легко. Однако без руководства по выводам тип, выведенный из неявных направляющих, будет std::valarray<int[3]> (руководство, сгенерированное из valarray(const T&, size_t), выигрывает, поскольку не требует преобразования массива в указатель). Это может быть продемонстрировано в вашем примере, если у нас есть оба конструктора A(const T&, std::size_t); и A(const T*, std::size_t);:

template <typename T>
struct A
{
    A(const T&, std::size_t);
    A(const T*, std::size_t);
};

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    A obj(a, 10);
}

// Result:
    call    A<int [10]>::A(int const (&) [10], unsigned long)

https://godbolt.org/z/nlFlVT

При добавлении руководства по выводам правильно выводится предполагаемый int вместо int[10]: https://godbolt.org/z/efj557

0 голосов
/ 08 октября 2019

Однако среди конструкторов класса есть только следующий подходящий конструктор (или я ошибаюсь?)

Также есть этот:

valarray( const T* vals, std::size_t count );

Что соответствует, когда массив, который вы передаете, распадается на указатель, что позволяет пример cppreference до compile .

...