忽略语法错误,您的代码未编译的原因是因为您不能部分特化函数模板,您只能部分特化类模板。但是,您可以重载函数。使用函数重载解决这个问题一点也不容易。我在下面详细介绍了两种技术,您可以使用它们来解决您的问题,其中第二种利用部分模板专业化。
首先,假设你有一个C++17编译器,你可以使用if constexpr和模板编程来获得想要的效果:
template <class SmartPtr>
struct Holder {
//this is a nested helper struct, which will allow us to deduce at compile-time
// whether SmartPtr is a std::unique_ptr or not, using function overloading
template<typename T>
struct is_unique_ptr{
template<typename TT>
constexpr static std::true_type test(std::unique_ptr<TT>*);
constexpr static std::false_type test(...);
using type = decltype(test(std::declval<T*>()));
constexpr static bool value = type::value;
};
//this is a nested helper struct, which will allow us to deduce at compile-time
// whether SmartPtr is a std::shared_ptr or not, using function overloading
template<typename T>
struct is_shared_ptr{
template<typename TT>
constexpr static std::true_type test(std::shared_ptr<TT>*);
constexpr static std::false_type test(...);
using type = decltype(test(std::declval<T*>()));
constexpr static bool value = type::value;
};
typedef typename SmartPtr::element_type value_type;
//default constructor will conditionally construct m_ptr depending on its type
Holder(){
if constexpr(is_unique_ptr<SmartPtr>::value){
m_ptr = std::make_unique<value_type>();
} else if constexpr(is_shared_ptr<SmartPtr>::value){
m_ptr = std::make_shared<value_type>();
} else {
m_ptr = new value_type{};
}
}
private:
SmartPtr m_ptr;
};
此解决方案不使用部分模板特化。但是,如果您坚持使用部分模板特化,或者您没有 c++17 编译器,则必须针对不同的指针类型对整个类进行特化:
//generic class Holder (identical to your initial implementation)
template <class SmartPtr>
struct Holder {
typedef typename SmartPtr::element_type value_type;
Holder()
: m_ptr(new value_type){
}
private:
SmartPtr m_ptr;
};
//this partial specialisation will be selected if template parameter is a std::unique_ptr
template<typename T>
struct Holder<std::unique_ptr<T>>{
using value_type = T;
Holder() : m_ptr(std::make_unique<value_type>()){
}
private:
std::unique_ptr<T> m_ptr;
};
//this partial specialisation will be selected if template parameter is a std::unique_ptr
template<typename T>
struct Holder<std::shared_ptr<T>>{
using value_type = T;
Holder() : m_ptr(std::make_shared<value_type>()) {
}
private:
std::shared_ptr<T> m_ptr;
};
像这样使用部分模板特化会导致代码膨胀。如果您决定使用此解决方案,您可能需要考虑将常用方法分解到一个基类中,所有特化都从该基类继承。这将有助于减少代码膨胀。