从模板实参的子类中推断函数模板形参

Infer function template parameter from a subclass of a template argument

本文关键字:函数模板 形参 子类 实参      更新时间:2023-10-16

我的问题类似于编译器何时可以推断模板参数?,但更复杂一点。

我想创建一个工厂函数,它可以推断其结果的类型,这样我就不必自己写了,而是使用auto代替(如下面的auto b = ...auto b3 = ...)。

我可以让代码与普通指针工作,但当我把它们改为unique_ptr的编译器抱怨。

下面是示例代码。

#include <iostream>
#include <memory>
template <typename T>
struct A {
    T fA() const { return T(); }
};
struct Aint : A<int> {};
template <typename T>
struct B {
    B(std::unique_ptr<A<T>> ptr) : ptr_(std::move(ptr)) {}
    B(A<T>* ptr) : ptr_(ptr) {}
    std::unique_ptr<A<T>> ptr_;
};
template <typename T>
std::unique_ptr<B<T>> CreateB(A<T>* a) {
    return std::unique_ptr<B<T>>(new B<T>(a));
}
template <typename T>
std::unique_ptr<B<T>> CreateBFromUnique(std::unique_ptr<A<T>> a) {
    return std::unique_ptr<B<T>>(new B<T>(std::move(a)));
}
int main() {
    auto b = CreateB(new Aint);
    std::cout << b->ptr_->fA() << "n";
    std::unique_ptr<Aint> a(new Aint);
    // call below fails to compile
    auto b2 = CreateBFromUnique(std::move(a));
    // This works fine.
    auto b3 = CreateBFromUnique<int>(std::move(a));
}

下面是clangs的输出(g++打印类似的消息):

templates1.cpp:34:15: error: no matching function for call to 'CreateBFromUnique'
    auto b2 = CreateBFromUnique(std::move(a));
              ^~~~~~~~~~~~~~~~~
templates1.cpp:24:23: note: candidate template ignored: could not match 'A<type-parameter-0-0>' against 'Aint'
std::unique_ptr<B<T>> CreateBFromUnique(std::unique_ptr<A<T>> a) {
                      ^

如何创建一个在这里编译的工厂函数?

PS元请求:什么是规范的方式来描述这个问题,以便谷歌容易?

当然有不止一种方法,但是…

#include <memory>
template <typename T> T AtypeHelper(A<T>*){}
template <typename T>
using Atype = decltype(AtypeHelper((T*)0));
template <typename U, typename T = Atype<U>>
  std::unique_ptr<B<T>> CreateBFromUnique(std::unique_ptr<U> a) {
  return MakeUnique<B<T>>(std::move(a));
}
int main() {
    auto b = CreateBFromUnique(MakeUnique<Aint>());
}

…您还可以考虑从A<T>导出typedef,使T易于提取为类似typename U::value_type的内容。