问题
I want to get a templatized way of finding if a type is a shared_ptr and based on that I want to have a new specialization of a function.
Example main function is,
template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME( RelaxedJSONInputArchive & ar, NameValuePair<T> & t )
{
std::cout << " CEREAL_LOAD_FUNCTION_NAME NameValuePair 1 " << std::endl;
ar.setNextName( t.name );
ar( t.value );
}
If t.value is shared_ptr then I want to have a different function specialization. I have tried below,
template <class T> inline
typename std::enable_if<is_pointer<T>::value, void>::type
CEREAL_LOAD_FUNCTION_NAME( RelaxedJSONInputArchive & ar, NameValuePair<T> & t )
{
std::cout << " CEREAL_LOAD_FUNCTION_NAME NameValuePair 2 " << std::endl;
ar.setNextName( t.name );
ar( t.value );
}
But it does not seem to work. These are part of c++11 cereal library. Which I am trying to customize.
回答1:
the following may help:
template<typename T> struct is_shared_ptr : std::false_type {};
template<typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
then you can do the following to get the correct function:
template <class T>
typename std::enable_if<is_shared_ptr<decltype(std::declval<T>().value)>::value, void>::type
func( T t )
{
std::cout << "shared ptr" << std::endl;
}
template <class T>
typename std::enable_if<!is_shared_ptr<decltype(std::declval<T>().value)>::value, void>::type
func( T t )
{
std::cout << "non shared" << std::endl;
}
live demo
回答2:
This is a basic case of template specialization. The following is a type trait that determines if a type T is a shared_ptr
or not. It can be used the same way std::is_pointer
, which you already use.
#include <memory>
#include <type_traits>
template<class T>
struct is_shared_ptr : std::false_type {};
template<class T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
Demonstration :
static_assert(is_shared_ptr<std::shared_ptr<int>>::value == true, "");
static_assert(is_shared_ptr<int>::value == false, "");
回答3:
If the type provided is itself a std::shared_ptr of some unknown type T, then the following use of SFINAE should help! Since all smart pointers provide a member type "element_type
" we can specialize for std::shared_ptr<T>
, std::weak_ptr<T>
, and std::unique_ptr<T>
as follows:
template<typename T, typename Enable = void>
struct is_smart_pointer
{
enum { value = false };
};
template<typename T>
struct is_smart_pointer<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::shared_ptr<typename T::element_type>>::value>::type>
{
enum { value = true };
};
template<typename T>
struct is_smart_pointer<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::unique_ptr<typename T::element_type>>::value>::type>
{
enum { value = true };
};
template<typename T>
struct is_smart_pointer<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::weak_ptr<typename T::element_type>>::value>::type>
{
enum { value = true };
};
来源:https://stackoverflow.com/questions/41853159/how-to-detect-if-a-type-is-shared-ptr-at-compile-time