模板类std :: valarray <T>

时间:2019-10-08 15:59:34

标签: c++ class c++17 type-deduction construct

在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 个答案:

答案 0 :(得分:1)

使用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

答案 1 :(得分:0)

  

但是在该类的构造函数中,只有以下适当的构造函数(或者我弄错了吗?)

还有一个:

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

这确实匹配,当您传入的数组衰减到指针时,允许cppreference examplecompile