考虑以下模板函数:
template <class T>
const T* DoSomething(const T& t)
{
auto& id = typeid(T);
cout << "Type is " << id.name() << ", and we have a ";
cout << "ref of one\n";
return &t;
}
template <class T>
T* DoSomething(T* t)
{
auto& id = typeid(T);
cout << "Type is " << id.name() << ", and we have a ";
cout << "pointer to one \n";
return t;
}
template <class T, template <class> class container>
T* DoSomething(const container<T>& t)
{
auto& type_id = typeid(T);
auto& container_id = typeid(container<T>);
cout << "Type is " << type_id.name() << ", and we have a ";
cout << container_id.name() << "of one\n";
return t.get();
}
template <class T, template <class,class> class container, template <class> class deleter = default_delete>
T* DoSomething(const container<T, deleter<T>>& t)
{
auto& type_id = typeid(T);
auto& container_id = typeid(container<T,deleter<T>>);
cout << "Type is " << type_id.name() << ", and we have a ";
cout << container_id.name() << "of one\n";
return t.get();
}
目标是能够将普通引用、指针或智能指针传递给它们,并使用重载和模板规范来调用正确的函数。以下驱动代码按预期工作:
char r('r');
DoSomething(r);
DoSomething(&r);
shared_ptr<char> s(new char ('s'));
unique_ptr<char> u(new char ('u'));
DoSomething(s);
DoSomething(u);
但是,考虑一下如果我们尝试这样做会发生什么:
vector<int> v {1,2};
DoSomething(v);
现在,我们得到一个编译错误。编译器决定使用的 DoSomething 版本是第 4 个版本。在这里面,我们引用了一个函数 get(),这个向量没有。如果编译器以某种方式选择 DoSomething 的第一个定义,它会编译得很好,并按我的意图工作。
那么我可以将第 3 和第 4 特化限制为仅在模板模板参数包含 get() 方法时匹配吗?有没有办法让这件事发生,也许使用特征、SFINAE 或其他更高级的模板技术?