Ari*_*Ari 12 c++ inheritance templates smart-pointers c++11
我正在尝试使用继承和模板参数推导std::shared_ptr.正如您在下面的示例代码中所看到的,我正在传递shared_ptr<Derived>一个模板化的非成员函数,该函数应该进行模板参数推导.如果我手动命名类型一切正常,如果我让它做模板参数推导它没有.它会看起来好像编译器无法弄清楚的类型,但该错误消息表明,它没有.我不确定这里发生了什么,我将不胜感激.(Visual Studio 2010)
#include <memory>
template <typename T>
class Base {};
class Derived : public Base<int> {};
template <typename T>
void func(std::shared_ptr<Base<T> > ptr) {};
int main(int argc, char* argv[])
{
std::shared_ptr<Base<int>> myfoo(std::shared_ptr<Derived>(new Derived)); // Compiles
func(myfoo); // Compiles
func<int>(std::shared_ptr<Derived>(new Derived)); // Compiles
func(std::shared_ptr<Derived>(new Derived)); // Doesn't compile. The error message suggests it did deduce the template argument.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误消息:
5> error C2664: 'func' : cannot convert parameter 1 from 'std::tr1::shared_ptr<_Ty>' to 'std::tr1::shared_ptr<_Ty>'
5> with
5> [
5> _Ty=Derived
5> ]
5> and
5> [
5> _Ty=Base<int>
5> ]
5> Binding to reference
5> followed by
5> Call to constructor 'std::tr1::shared_ptr<_Ty>::shared_ptr<Derived>(std::tr1::shared_ptr<Derived> &&,void **)'
5> with
5> [
5> _Ty=Base<int>
5> ]
5> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\memory(1532) : see declaration of 'std::tr1::shared_ptr<_Ty>::shared_ptr'
5> with
5> [
5> _Ty=Base<int>
5> ]
5>
Run Code Online (Sandbox Code Playgroud)
And*_*owl 10
虽然编译器可以在执行类型推导时执行派生到基本的转换,std::shared_ptr<Derived>但它本身并非衍生自std::shared_ptr<Base<int>>.
两者之间存在用户定义的转换,允许shared_ptr在多态性方面表现得像常规指针,但编译器在执行类型推导时不会考虑用户定义的转换.
不考虑用户定义conversiosn,编译器不能推断出T,这将使shared_ptr<Base<T>>任何相同shared_ptr<Derived>或基类的shared_ptr<Derived>(再次,shared_ptr<Base<int>>是不基类的shared_ptr<Derived>).
因此,类型扣除失败.
要解决这个问题,可以让函数的参数变得简单,shared_ptr<T> 并添加一个SFINAE约束,以确保只有当参数的类型派生自(或者是)Base类的实例时才会选择重载.模板:
#include <type_traits>
namespace detail
{
template<typename T>
void deducer(Base<T>);
bool deducer(...);
}
template <typename T, typename std::enable_if<
std::is_same<
decltype(detail::deducer(std::declval<T>())),
void
>::value>::type* = nullptr>
void func(std::shared_ptr<T> ptr)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是一个实例.