Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
#include <string>
#include <iostream>
#define static_type(name) static constexpr const char* type_name() { return name; }
struct disabled { static_type("disabled"); };
struct deferred { static_type("deferred"); };
struct deadline { static_type("deadline"); };
template<typename Expected, typename...T>
struct match { typedef disabled type; };
template <typename Expected, typename...T>
struct match<Expected, Expected, T...> { typedef Expected type; };
template <typename 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, Plugins...>::type deferred_;
typedef typename match<deadline, 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>::type_name() << std::endl;
cout << container<int, deferred>::type_name() << std::endl;
cout << container<int, deferred, deadline>::type_name() << std::endl;
cout << container<int, deadline, deferred>::type_name() << std::endl;
}
boost::transform_iterator:template <class UnaryFunction,
class Iterator,
class Reference = use_default,
class Value = use_default>
class transform_iterator
Reference отвечает за член класса reference и, выставляя Reference, мы управляем «свойством» reference и т.д. И порядок имеет значение — чтобы выставить reference, мы задаём его значение 3м аргументом. Как Вы и сказали:Но мы прекрасно понимаем, что как только мы поменяли два параметр у нас получится совершенно не то чего мы ожидали
Способ который я хочу показать не позволяет специализировать шаблон произвольным типом.
struct deferred
template <typename T>
struct deferred_tag { typedef T type; };
cout << container<int, deferred_tag<deferred_type_2>, deadline_tag<deadline_type>>::type_name() << std::endl;
#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;
}
container<T, DEADLINE|DEFERRED> и container<T, DEFERRED|DEADLINE> дают один и тот же тип (в отличие от приведенного в статье подхода).#include <iostream>
#define static_type(name) static constexpr const char* type_name() { return name; }
struct disabled { static_type("disabled"); };
struct deferred { static_type("deferred"); };
struct deadline { static_type("deadline"); };
enum {
DEFERRED = 1,
DEADLINE = 2,
MAX_POWER_OF_TWO = 4
};
template<int V, class A, class B>
struct type_selector {
typedef B type;
};
template<class A, class B>
struct type_selector<0, A, B> {
typedef A type;
};
template<class T, int Plugins = 0>
struct container
{
static_assert(Plugins >= 0 && Plugins < MAX_POWER_OF_TWO, "Invalid flags");
typedef typename type_selector<Plugins & DEFERRED, disabled, deferred>::type
deferred_type;
typedef typename type_selector<Plugins & DEADLINE, disabled, deadline>::type
deadline_type;
static std::string type_name() {
return std::string("container<") + deferred_type::type_name()
+ ", " + deadline_type::type_name() + ">";
}
};
int main() {
using namespace std;
cout << container<int>::type_name() << std::endl;
cout << container<int, DEADLINE>::type_name() << std::endl;
cout << container<int, DEFERRED>::type_name() << std::endl;
cout << container<int, DEFERRED | DEADLINE>::type_name() << std::endl;
//cout << container<int, 6>::type_name() << std::endl; //Ошибка компиляции
return 0;
}
Произвольный порядок списка инициализации шаблона