c++ - 从继承类型推导模板参数

标签 c++ templates polymorphism c++14

我想要如下设置:

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 failedmismatched types 'a<T>' and 'b' .这是不言自明的。我可以通过写 do_foo<int>(std::make_unique<b>()); 来帮助编译器。 ,但后来我通过写 int 重复我自己两次。
在这种情况下,有没有办法让编译器推断出模板参数?你怎么称呼这种行为?我尝试搜索诸如“继承类型的模板类型推导”、“多态模板推导”等内容。

最佳答案

Is there a way to get the compiler to deduce the template parameter in this case?


不。不在 C++14(甚至 C++20)中。

And what would you call this behaviour?


符合标准。具体而言,本段适用于:

[temp.deduct.call]

4 In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:

  • If the original P is a reference type, the deduced A (i.e., the type referred to by the reference) can be more cv-qualified than the transformed A.
  • The transformed A can be another pointer or pointer to member type that can be converted to the deduced A via a qualification conversion ([conv.qual]).
  • If P is a class and P has the form simple-template-id, then the transformed A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class pointed to by the 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特化本身与继承无关。所以它们与子弹不匹配,并且演绎失败。
但这并不意味着像 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;博士 :unique_ptr<T>特化不能复制原始指针的行为。它们不是从 unique_ptr 的特化继承而来的。在 T的基地。也许如果反射出现在 C++ 中,我们将能够元编程一个具有这种行为的智能指针。

关于c++ - 从继承类型推导模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66356320/

相关文章:

c++ - sizeof(enum) 与 sizeof(std::underlying_type<Enum>::type) 可以不同吗?

c++ - 如何以灰度读入视频文件

c++ - 具有 pqxx 结果的模板函数

c# - 覆盖等于和类型转换

c++ - 从基类方法调用子类虚方法

c++ - 使用继承时类的大小是多少?

c++ - 调试堆内存泄漏检测 - 奇怪的结果?

c++ - 为什么我将函数命名为 `swap` 时会出现模板错误,但 `Swap` 没问题?

c++ - 在 C++ 模板特化中添加基类

polymorphism - 我可以使用 pa_monad 来确保 η 扩展吗?