我想要类似以下的设置:
template <typename T> class a {};
class b : public a<int> {};
template <typename T>
void do_foo(std::unique_ptr<a<T>> foo)
{
// Do something with foo
}
int main()
{
do_foo(std::make_unique<b>());
}
这并没有加上注释template argument deduction/substitution failed
和的注释mismatched types 'a<T>' and 'b'
。这很不言自明。我可以通过编写来帮助编译器do_foo<int>(std::make_unique<b>());
,但是接下来我要通过编写int
两次来重复自己。
在这种情况下,是否有办法让编译器推断出模板参数?您将这种行为称为什么?我尝试搜索“继承类型的模板类型归纳”,“多态模板归纳”等内容。
在这种情况下,是否有办法让编译器推断出模板参数?
不。不是在C ++ 14(甚至C ++ 20)中。
您将这种行为称为什么?
符合标准。具体来说,本款适用于:
[临时扣减电话]
4通常,推论过程会尝试查找将使推论
A
相同的模板参数值A
(在A
如上所述对类型进行转换之后)。但是,在三种情况下可能会有所不同:
- 如果原始
P
类型是引用类型,则推导A
(即,引用所引用的类型)可以比transformed更具cv限定性A
。- 转换后的
A
可以是可以A
通过资格转换([conv.qual])转换为推导的成员类型的另一种指针或指针。- 如果
P
是类,P
并且形式为simple-template-id,则转换后的对象A
可以是deduced的派生类A
。同样,如果P
是指向形式为simple-template-id的类的指针,则transformdA
可以是由deduced指向的派生类的指针A
。
这是一个模板参数可以从函数的参数来推断有效,即使它不函数参数的模式相匹配的情况下的详尽清单准确。第一和第二个子弹处理类似
template<class A1> void func(A1&){}
template<class A2> void func(A2*){}
int main() {
const int i = 1;
func(i); // A1 = const int
func(&i); // A2 = const int
}
第三点是最接近我们的情况。从模板专业化派生的类可用于推导与其基础有关的模板参数。为什么在您的情况下不起作用?由于函数模板参数为unique_ptr<a<T>>
,而您调用它的参数为unique_ptr<b>
。该unique_ptr
专业有没有自己的继承关系。因此他们与子弹不匹配,推论失败了。
但这并不意味着类似wrapper的方法unique_ptr
可以完全防止模板参数的推导。例如:
template <typename> struct A {};
struct B : A<int> {};
template<typename> struct wrapper{};
template<> struct wrapper<B> : wrapper<A<int>> {};
template<typename T>
void do_smth(wrapper<A<T>>) {}
int main() {
do_smth(wrapper<B>{});
}
在这种情况下,wrapper<B>
来自wrapper<A<int>>
。因此,第三个项目符号是适用的。通过模板参数推导的复杂(递归)过程,它可以B
进行匹配A<T>
和推导T = int
。
TL; DR:unique_ptr<T>
专业化无法复制原始指针的行为。它们不继承unique_ptr
overT
的基础的专业知识。也许,如果反射曾经说到C ++,我们将能够元程序的智能指针确实行为是那样的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句