使用默认模板参数的多态 class 的模板推导失败
Template deduction fails for polymorphic class with default template parameters
考虑这个例子:
#include <memory>
template<typename T>
class A {};
template<typename T1, typename T2>
class B: public A<T1> {};
template<typename T = int>
void foo(std::shared_ptr< A<T> > test)
{
}
int main()
{
auto p = std::make_shared<B<int, int>>();
foo<int>(p); // Works
foo<>(p); // Does not work
foo(p); // Does not work
}
我试图在不明确指定 foo 的类型 T 的情况下编译它,但它不起作用。我不确定为什么就好像我显式地指定了 T 类型一样,它工作得很好,但如果我这样做了,它就无法编译,即使我已经告诉编译器如果我不这样做的话 T 类型应该是什么明确指定。
我明白为什么编译器不能推导出类型 T,但为什么它不能在我不指定时使用我的默认类型 T?我该如何解决这个问题,"proper" 的方法是什么?
问题与默认模板参数无关。相反,p
(std::shared_ptr<B<int, int>>
) 的类型无法与模板 foo
的 std::shared_ptr<T>
参数匹配:在模板参数推导期间,不考虑转换,并将对派生 class 实例的引用作为基础 class 引用传递确实是一种转换。
您可以通过显式向上转换 std::shared_ptr
管理的指针来解决此问题。
std::shared_ptr<A<int>> p = std::make_shared<B<int, int>>();
现在,这些调用将按预期进行:
foo<>(p); // Ok, argument matches the signature
foo(p); // Same...
请注意,模板参数类型是否出现在函数模板的参数列表中(使推导成为可能)会有很大的不同。考虑这两个模板,
template <class T = int> void foo(T&&)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T = int> void bar(double)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
两者都有默认类型int
,但是当它们像这样实例化时
foo<>(0.0); // outputs: void foo(T&&) [with T = double]
bar<>(0.0); // outputs: void bar(double) [with T = int]
第一个实例化使用函数参数推导模板参数(结果为 double
),而第二个实例化不推导任何内容并默认为 int
.
考虑这个例子:
#include <memory>
template<typename T>
class A {};
template<typename T1, typename T2>
class B: public A<T1> {};
template<typename T = int>
void foo(std::shared_ptr< A<T> > test)
{
}
int main()
{
auto p = std::make_shared<B<int, int>>();
foo<int>(p); // Works
foo<>(p); // Does not work
foo(p); // Does not work
}
我试图在不明确指定 foo 的类型 T 的情况下编译它,但它不起作用。我不确定为什么就好像我显式地指定了 T 类型一样,它工作得很好,但如果我这样做了,它就无法编译,即使我已经告诉编译器如果我不这样做的话 T 类型应该是什么明确指定。
我明白为什么编译器不能推导出类型 T,但为什么它不能在我不指定时使用我的默认类型 T?我该如何解决这个问题,"proper" 的方法是什么?
问题与默认模板参数无关。相反,p
(std::shared_ptr<B<int, int>>
) 的类型无法与模板 foo
的 std::shared_ptr<T>
参数匹配:在模板参数推导期间,不考虑转换,并将对派生 class 实例的引用作为基础 class 引用传递确实是一种转换。
您可以通过显式向上转换 std::shared_ptr
管理的指针来解决此问题。
std::shared_ptr<A<int>> p = std::make_shared<B<int, int>>();
现在,这些调用将按预期进行:
foo<>(p); // Ok, argument matches the signature
foo(p); // Same...
请注意,模板参数类型是否出现在函数模板的参数列表中(使推导成为可能)会有很大的不同。考虑这两个模板,
template <class T = int> void foo(T&&)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T = int> void bar(double)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
两者都有默认类型int
,但是当它们像这样实例化时
foo<>(0.0); // outputs: void foo(T&&) [with T = double]
bar<>(0.0); // outputs: void bar(double) [with T = int]
第一个实例化使用函数参数推导模板参数(结果为 double
),而第二个实例化不推导任何内容并默认为 int
.