通过std:is_base_of推导模板参数
Deduce template parameter through std:is_base_of
考虑以下示例:
#include <memory>
template<class T>
class RefSP {
private:
std::shared_ptr<T> p;
public:
template<class A>
RefSP(A&& v) : p(std::forward<A>(p)) {}
};
template <
class T,
class U,
typename std::enable_if<std::is_base_of<std::shared_ptr<U>, T>::value>::type* = nullptr>
inline RefSP<U>*
make_ref_sp(T&& p)
{
return new RefSP<U>(std::forward<T>(p));
}
int main()
{
auto sp = std::make_shared<int>(42);
auto x = make_ref_sp(sp);
}
我遇到编译错误
In function 'int main()':
25:28: error: no matching function for call to 'make_ref_sp(std::shared_ptr<int>&)'
25:28: note: candidate is:
17:1: note: template<class T, class U, typename std::enable_if<std::is_base_of<std::shared_ptr<_Tp2>, T>::value>::type* <anonymous> > RefSP<U> make_ref_sp(T&&)
17:1: note: template argument deduction/substitution failed:
25:28: note: couldn't deduce template parameter 'U'
问题是,我如何修复代码,以便在保留移动语义的同时推断 U
T
是 std::shared_ptr<U>
。
std::is_base_of
是继承性状...
你需要特殊的特质:
template <typename> struct is_shared_ptr : std::false_type {};
template <typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
{
// Possibly add information here
// using element_type = T;
};
template <
class T,
typename std::enable_if<is_shared_ptr<typename std::decay<T>::type>::value, int>::type = 0>
RefSP<typename std::decay<T>::type::element_type>
make_ref_sp(T&& p)
{
return RefSP<U>(std::forward<T>(p));
}
我会简单地做:
#include <memory>
template <class T>
class RefSP {
private:
std::shared_ptr<T> p;
public:
explicit RefSP(std::shared_ptr<T>&& v) : p(std::move(v)) {}
};
template <class T>
RefSP<T> make_ref_sp(std::shared_ptr<T>&& p)
{
return RefSP<T>(std::move(p));
}
int main()
{
auto sp = std::make_shared<int>(42);
auto x = make_ref_sp(std::move(sp));
}
如果你想允许隐式复制,你可以添加相应的重载:
template <class T>
RefSP<T>::RefSP(const std::shared_ptr<T>& v) : p(v) {}
template <class T>
RefSP<T> make_ref_sp(const std::shared_ptr<T>& p)
{
return RefSP<T>(p);
}
如果您不想编写重载并让用户在(隐式)复制和移动之间进行选择,请将所有重载替换为:
template <class T>
RefSP<T>::RefSP(std::shared_ptr<T> v) : p(std::move(v)) {}
template <class T>
RefSP<T> make_ref_sp(std::shared_ptr<T> p)
{
return RefSP<T>(std::move(p));
}
考虑以下示例:
#include <memory>
template<class T>
class RefSP {
private:
std::shared_ptr<T> p;
public:
template<class A>
RefSP(A&& v) : p(std::forward<A>(p)) {}
};
template <
class T,
class U,
typename std::enable_if<std::is_base_of<std::shared_ptr<U>, T>::value>::type* = nullptr>
inline RefSP<U>*
make_ref_sp(T&& p)
{
return new RefSP<U>(std::forward<T>(p));
}
int main()
{
auto sp = std::make_shared<int>(42);
auto x = make_ref_sp(sp);
}
我遇到编译错误
In function 'int main()':
25:28: error: no matching function for call to 'make_ref_sp(std::shared_ptr<int>&)'
25:28: note: candidate is:
17:1: note: template<class T, class U, typename std::enable_if<std::is_base_of<std::shared_ptr<_Tp2>, T>::value>::type* <anonymous> > RefSP<U> make_ref_sp(T&&)
17:1: note: template argument deduction/substitution failed:
25:28: note: couldn't deduce template parameter 'U'
问题是,我如何修复代码,以便在保留移动语义的同时推断 U
T
是 std::shared_ptr<U>
。
std::is_base_of
是继承性状...
你需要特殊的特质:
template <typename> struct is_shared_ptr : std::false_type {};
template <typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
{
// Possibly add information here
// using element_type = T;
};
template <
class T,
typename std::enable_if<is_shared_ptr<typename std::decay<T>::type>::value, int>::type = 0>
RefSP<typename std::decay<T>::type::element_type>
make_ref_sp(T&& p)
{
return RefSP<U>(std::forward<T>(p));
}
我会简单地做:
#include <memory>
template <class T>
class RefSP {
private:
std::shared_ptr<T> p;
public:
explicit RefSP(std::shared_ptr<T>&& v) : p(std::move(v)) {}
};
template <class T>
RefSP<T> make_ref_sp(std::shared_ptr<T>&& p)
{
return RefSP<T>(std::move(p));
}
int main()
{
auto sp = std::make_shared<int>(42);
auto x = make_ref_sp(std::move(sp));
}
如果你想允许隐式复制,你可以添加相应的重载:
template <class T>
RefSP<T>::RefSP(const std::shared_ptr<T>& v) : p(v) {}
template <class T>
RefSP<T> make_ref_sp(const std::shared_ptr<T>& p)
{
return RefSP<T>(p);
}
如果您不想编写重载并让用户在(隐式)复制和移动之间进行选择,请将所有重载替换为:
template <class T>
RefSP<T>::RefSP(std::shared_ptr<T> v) : p(std::move(v)) {}
template <class T>
RefSP<T> make_ref_sp(std::shared_ptr<T> p)
{
return RefSP<T>(std::move(p));
}