You could use SFINAE, but then I don't really see the point to have this inside a function anymore. It's pretty redundant.
#include <memory>
#include <type_traits>
template <class T, class... Args>
typename std::enable_if<
std::is_same<T, std::shared_ptr<typename T::element_type>>::value, T>::type
createObject(Args&&... args) {
// running some code
return std::make_shared<typename T::element_type>(std::forward<Args>(args)...);
}
template <class T, class... Args>
typename std::enable_if<
std::is_same<T, std::unique_ptr<typename T::element_type>>::value, T>::type
createObject(Args&&... args) {
// running some code
return std::make_unique<typename T::element_type>(std::forward<Args>(args)...);
}
int main() {
auto s = createObject<std::shared_ptr<int>>(1);
auto u = createObject<std::unique_ptr<int>>(1);
}
A little bit more compact but essentially the same idea with a scoped enum
#include <memory>
enum class ptr_t { shared, unique };
template <ptr_t P, class T, class... Args>
typename std::enable_if<P == ptr_t::shared, std::shared_ptr<T>>::type
createObject(Args&&... args) {
// running some code
return std::make_shared<T>(std::forward<Args>(args)...);
}
template <ptr_t P, class T, class... Args>
typename std::enable_if<P == ptr_t::unique, std::unique_ptr<T>>::type
createObject(Args&&... args) {
// running some code
return std::make_unique<T>(std::forward<Args>(args)...);
}
int main() {
auto s = createObject<ptr_t::shared, int>(1);
auto u = createObject<ptr_t::unique, int>(1);
}
In C++17 you of course use if constexpr
in both cases rather than SFINAE.
#include <memory>
enum class ptr_t { shared, unique };
template <ptr_t P, class T, class... Args>
decltype(auto) createObject(Args &&... args) {
// running some code
if constexpr (P == ptr_t::shared) {
return std::make_shared<T>(std::forward<Args>(args)...);
} else if (P == ptr_t::unique) {
return std::make_unique<T>(std::forward<Args>(args)...);
}
}