Определение шаблонной конструкции
Если я введу create() то должен возвращать Object соответственно. Но проблема заключается в шаблонной конструкций. Вот небольшой код
#include <stdio.h>
using namespace std;
class xObject;
class xGameObject;
typedef shared_ptr<xObject> Object; //буду использовать ее как смарт указатель.
typedef shared_ptr<xGameObject> GameObject; // естественно для xGameObject
//Собственно этот create для xObject оригинал класс...
template<typename _xTy, typename _ShareTy = shared_ptr<_xTy>>
_ShareTy create();
//Собственно этот create для Object для смарт указателей...
template<typename _ShareTy>
_ShareTy create();
//foo Создаю объект
void main(void)
{
//С обычным классом
auto sharedObject = create<xGameObject();
//С смарт типом
auto sharedObject2 = create<GameObject>();
}
Ответы (2 шт):
Вот шаблон, который позволяет определить, является ли некоторый тип специализацией некоторого шаблона:
namespace impl
{
template <typename A, template <typename...> typename B>
struct is_specialization_of : std::false_type {};
template <template <typename...> typename T, typename ...P>
struct is_specialization_of<T<P...>, T> : std::true_type {};
}
template <typename A, template <typename...> typename B>
inline constexpr bool is_specialization_of = impl::is_specialization_of<A, B>::value;
То есть is_specialization_of<std::shared_ptr<int>, std::shared_ptr> == true, а какой-нибудь is_specialization_of<int, std::shared_ptr> == false.
А теперь или используем этот шаблон в SFINAE:
template <typename T, std::enable_if_t<is_specialization_of<T, std::shared_ptr>, std::nullptr_t> = nullptr>
T create() {std::cout << "1\n"; return {};}
template <typename T, std::enable_if_t<!is_specialization_of<T, std::shared_ptr>, std::nullptr_t> = nullptr>
T create() {std::cout << "2\n"; return {};}
Или берем if constexpr:
template <typename T>
T create()
{
if constexpr (is_specialization_of<T, std::shared_ptr>)
std::cout << "1\n";
else
std::cout << "2\n";
return {};
}
Или, если компилятор достаточно свежий, то можно выпендриться и вообще сделать концепт (нужен C++20):
template <typename A, template <typename...> typename B>
concept specialization_of = impl::is_specialization_of<A, B>::value;
template <specialization_of<std::shared_ptr> T>
T create() {std::cout << "1\n"; return {};}
template <typename T>
T create() {std::cout << "2\n"; return {};}
Этого можно достичь с помощью частичной специализации. Для функция она не разрешается, однако тривиально реализуется через класс, при этом отсутствует необходимость писать дополнительные трейты, использовать SFINAE или концепты:
template< typename x_Object >
class creator
{
public: static x_Object create() { return {}; }
};
template< typename x_Object >
class creator< ::std::shared_ptr< x_Object > >
{
public: static ::std::shared_ptr< x_Object > create() { return {}; }
};
// функция избавляет тольк от лишнего написания ::create, так можно обойтись и без нее
template< typename x_Object >
x_Object create()
{
return creator< x_Object >::create();
}