#include <string>
#include <iostream>

#define static_type(name) static constexpr const char* type_name() { return name; } 

struct disabled_type { static_type("disabled"); };

struct deferred_type { static_type("deferred"); };
struct deferred_type_2 { static_type("deferred2!"); };

struct deadline_type { static_type("deadline"); };
struct deadline_type_2 { static_type("deadline2!"); };

template <typename T = deferred_type>
struct deferred_tag { typedef T type; };

template <typename T = deadline_type>
struct deadline_tag {typedef T type; };

template<template <class> class Expected, typename...T> 
struct match { typedef disabled_type type; };

template <typename V, template <class> class Expected, typename...T>
struct match<Expected, Expected<V>, T...> { typedef typename Expected<V>::type type; };

template <template <class> class Expected, typename Actual, typename...T>
struct match<Expected, Actual, T...> { typedef typename match<Expected, T...>::type type; };


template<class T, typename... Plugins>
struct container
{
    typedef typename match<deferred_tag, Plugins...>::type deferred_;
    typedef typename match<deadline_tag, Plugins...>::type deadline_;
    
    static std::string type_name()
    {
    	return std::string("container<") + deferred_::type_name() + ", " + deadline_::type_name() + ">";
    }
};

int main()
{
	using namespace std;
	cout << container<int>::type_name() << std::endl;
    cout << container<int, deadline_tag<deadline_type>>::type_name() << std::endl;
    cout << container<int, deferred_tag<deferred_type>>::type_name() << std::endl;
    cout << container<int, deferred_tag<deferred_type>, deadline_tag<deadline_type>>::type_name() << std::endl;
    cout << container<int, deadline_tag<deadline_type>, deferred_tag<deferred_type>>::type_name() << std::endl;

    cout << container<int, deadline_tag<deadline_type_2>, deferred_tag<deferred_type_2>>::type_name() << std::endl;
    cout << container<int, deadline_tag<deadline_type_2>>::type_name() << std::endl;
    cout << container<int, deferred_tag<deferred_type_2>, deadline_tag<>>::type_name() << std::endl;
}
