templated class 中templated class 成员的扣除

Deduction of templated class member in templated class

我正在利用 C++17 的新功能在模板化 class 中推导 class 成员类型。具体来说,我是这样做的:

#include <array>
#include <iostream>

template <std::size_t N = 0>
class A
{
public:
    using Array = std::array<int, N>;

    A(const Array& arr) : myArr{arr} {}
    A() = default;

    void show() { std::cout << N << std::endl; }

private:
    Array myArr;
};

当我构造 A 而不明确指示 N 时,编译器正确匹配构造函数并正确推导 N

std::array<int, 3> data{1, 2, 3};
A a1{data};
A a2;

a1.show(); // prints 3
a2.show(); // prints 0

然而,一旦我在 A 中引入另一个模板参数,这个魔法就被破坏了,像这样:

template <typename T, std::size_t N = 0>
class A
{
    ... // same content, no use of T
}

当我构造 A 传递任何 T 时,它不再编译:

A<int> a1{data};
A<int> a2;

编译器在所有情况下都推导 N=0 并且无法将输入 std::array<int, 3> 分配给构造函数中的推导参数 std::array<int, 0>:

error: no matching function for call to ‘A<int>::A(<brace-enclosed initializer list>)’
A<int> a1{data};

note: candidate: ‘A<T, N>::A(const Array&) [with T = int; long unsigned int N = 0; A<T, N>::Array = std::array<int, 0>]’
A(const Array& arr) : myArr{arr} {}

note:  no known conversion for argument 1 from ‘std::array<int, 3>’ to ‘const Array&’ {aka ‘const std::array<int, 0>&’}
A(const Array& arr) : myArr{arr} {}

谁能解释一下为什么会这样,是否有解决办法?

提前致谢!

演绎指南不做部分匹配。

合成与否

第一种情况,编译器综合推导指南

template<std::size_t N>
A(std::array<int,N>const&)->A<N>;

一旦您传递任何模板参数,就不会使用演绎指南。没有部分匹配。

请参阅 https://en.cppreference.com/w/cpp/language/class_template_argument_deduction 了解您所谓的魔法的正确描述。

写一个make函数,或者省略int

至于为什么,可能是反向兼容性的恐惧和 KISS 原则。