Autodetect Base类的类型参数

时间:2014-12-03 12:03:00

标签: c++ templates c++11 template-deduction

我有以下代码可以正常工作:

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>我想要错误(自动调解应该失败)。

1 个答案:

答案 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的定义,可以轻松修复此问题。