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 原则。
我正在利用 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 原则。