#include <algorithm>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>

template <class T, template <class...> class TT>
struct is_instantiation_of : std::false_type
{};

template <template <class... > class TT, class... A>
struct is_instantiation_of<TT<A...>, TT> : std::true_type
{};

static_assert(is_instantiation_of<std::shared_ptr<int>, std::shared_ptr>::value, "int");
static_assert(is_instantiation_of<std::shared_ptr<double>, std::shared_ptr>::value, "double");
static_assert(is_instantiation_of<std::string, std::basic_string>::value, "str");
static_assert(!is_instantiation_of<std::shared_ptr<int>, std::weak_ptr>::value, "NO");

int main()
{
}