我有以下代码可以正常工作:
template<typename T>
class Base {
virtual void call(T) = 0;
};
class Derived : public Base<int> {
void call(int);
}
template<typename T>
void registerBase(const Base<T>& ref) {}
当调用T
时,此方法可以将int
类型自动检测为registerBase(Derived())
。当我切换到shared_ptr
时出现问题:
template<typename T, typename Q>
void registerBase(shared_ptr<Q> ptr) {
static_assert(is_base_of<Base<T>, Q>::value, "Have to supply a type extending Base<...>");
}
我可以防止非法类型,但我似乎无法自动检测类型T
。我可以使用一些技巧自动将shared_ptr向下转换为Base<T>
,因此模板推导有效吗?或者是否有另一种方法可以找到类型名T
?
PS:如果Q
扩展乘以Base<T>
我想要错误(自动调解应该失败)。
答案 0 :(得分:1)
可能有很多方法可以做到这一点。这是一个:
template<class T>
T helper(const Base<T> &); // not defined
template<class Q>
using base_param = decltype(helper(std::declval<Q>()));
在实际代码中,您可能希望将helper
放在details
命名空间中(可能还会更改名称)。
如果你有一个奇怪的T
是一个无法返回的类型 - 例如一个数组类型,这将会中断。通过将helper
的返回类型更改为例如identity<T>
,然后相应地更改base_param
的定义,可以轻松修复此问题。