基于智能指针的*internal*类型专门化模板



我有一个类,它封装了一个通用的"智能指针"(可以是unique_ptrshared_ptr等(。

我试图专门化构造函数,以便调用适当的make_uniquemake_shared等,但我不确定正确的语法。

以下是想法(实时链接(:

template <class SmartPtr>
struct Holder {
typedef typename SmartPtr::element_type value_type;
Holder()
: m_ptr(new value_type) // The fallback implementation calls 'new' directly.
{}
private:
SmartPtr m_ptr;
};
// THIS DOES NOT COMPILE
// Notice the "T" type, which is not declared anywhere.
// How do I declare this sort of thing properly?
template<>
Holder<shared_ptr<T>>::Holder
: m_ptr(make_shared<T>())
{}

希望这是清楚的。我想基于智能指针进行专门化,但我也需要访问智能指针管理的底层类型。

这是C++14,但我也对其他标准的想法感兴趣。


EDIT:一些类似的问题,但在这种情况下并不完全适用(或者如果适用,我不清楚所需的转换(。

  • 用泛型类专门化模板函数
  • C++如何使用vector<T>

忽略语法错误,您的代码没有编译的原因是,您不能部分专门化函数模板,只能部分专门化类模板。但是,您可以重载函数。使用函数重载来解决这个问题一点也不容易。我在下面详细介绍了两种技术,你可以用它们来解决你的问题,第二种技术利用部分模板专业化。

首先,假设您有一个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;
};

像这样使用部分模板专业化可能会导致代码膨胀。如果您决定使用此解决方案,您可能需要考虑将通用方法分解为基类,所有专业化都从基类继承。这将有助于减少代码膨胀。

我想我已经明白了(实时链接(:

关键是要有一个带有enable_if的模板化构造函数来确定它是否是一个有效的选择。

template <class SmartPtr>
struct Holder {
typedef typename SmartPtr::element_type value_type;
Holder()
: m_ptr(new value_type)
{}
template <class T = value_type>
Holder(std::enable_if_t<  std::is_same<shared_ptr<T>,SmartPtr>::value  >* = 0)
: m_ptr(make_shared<T>())
{}
private:
SmartPtr m_ptr;

};

可能还有更好的方法——is_same检查似乎有点麻烦。但现在已经足够了。

相关内容

最新更新