At least this compiles and works:
#include <iostream>
#include <memory>
#include <string>
template <class T>
std::shared_ptr<T> make_instance();
template <class T> requires std::is_default_constructible_v<T>
std::shared_ptr<T> make_instance()
{
return std::make_shared<T>();
}
template <>
std::shared_ptr<int> make_instance()
{
return std::make_shared<int>(25);
}
template <>
std::shared_ptr<std::string> make_instance()
{
return std::make_shared<std::string>("abc");
}
struct A { std::string val; };
int main()
{
std::shared_ptr<int> p_int = make_instance<int>();
std::shared_ptr<std::string> p_string = make_instance<std::string>();
std::shared_ptr<A> p_a = make_instance<A>();
std::cout << *p_int << ", " << *p_string << std::endl;
}