#include <iostream>
#include <set>
enum Type{ one, two, three, four, five };
struct A{ Type t; A(Type t):t(t){} };
int _tmain(int argc, _TCHAR* argv[])
{
// два разных множества
std::set<Type> s1;
s1.insert(one);
s1.insert(two);
s1.insert(three);
std::set<Type> s2;
s2.insert(four);
s2.insert(five);
// два объекта одного класса с разным типом чего-то внутри
A a1(one);
A a4(four);
// если тип чего-то внутри принадлежит множеству 1, то делаем какие-то действияif(s1.find(a1.t) != s1.end())
std::cout << "in s1 set" << std::endl;
// то же самое для второго объектаif(s2.find(a4.t) != s2.end())
std::cout << "in s2 set" << std::endl;
return 0;
}
Мне бы хотелось превратить его во что-то такое:
#include <iostream>
enum Type{ one, two, three, four, five };
struct A{ Type t; A(Type t):t(t){} };
template<Type t>struct Test{ static bool In(Type t); };
template<>static bool Test<one>::In(Type t){ return one == t; }; // здесь все окtemplate<>static bool Test<two>::In(Type t){ return two == t; };
template<>static bool Test<three, four, five>::In(Type t) // а вот это я делать не умею :(
{
return three == t || four == t || five == t;
};
int _tmain(int argc, _TCHAR* argv[])
{
A a1(one);
// тут вместо условий пока просто вывожу результат проверки
std::cout << Test<one>::In(a1.t) << std::endl;
std::cout << Test<two>::In(a1.t) << std::endl;
std::cout << Test<three, four, five>::In(a1.t) << std::endl; // соответсвенно это не компилится :(return 0;
}
Как это можно сделать наиболее "легким" способом? А может не стоит огород городить и оставить как есть? Хотелось бы найти наиболее правильное решение. Спасибо.
Здравствуйте, Аноним, Вы писали:
А>Как это можно сделать наиболее "легким" способом? А может не стоит огород городить и оставить как есть? Хотелось бы найти наиболее правильное решение. Спасибо.
Здравствуйте, <Аноним>, Вы писали:
А> // два разных множества
... А> // два объекта одного класса с разным типом чего-то внутри
... А> // если тип чего-то внутри принадлежит множеству 1, то делаем какие-то действия
Если задача именно таких масштабов и показан типичный сценарий использования, почему бы не задействовать "тупой и циничный" вариант:
#include <iostream>
enum Type{ one, two, three, four, five };
struct A{ Type t; A(Type t):t(t){} };
template < int Size >
bool In( const Type (&arr)[Size], Type q )
{
for( int i=0; i<Size; ++i )
if( arr[i]==q )
return true;
return false;
}
int main()
{
Type s1[] = {one, two, three};
Type s2[] = {four, five};
A a1(one);
A a4(four);
std::cout <<In(s1, a1.t) <<std::endl;
std::cout <<In(s1, a4.t) <<std::endl;
std::cout <<In(s2, a1.t) <<std::endl;
std::cout <<In(s2, a4.t) <<std::endl;
return 0;
}
А так — можно соорудить конструкцию по мотивам TypeList и Int2Type Александреску, но надо ли? К тому же, от проблемы с переменным числом параметров в шаблоне оно не избавляет, да и проверяемое значение должно быть известно во время компиляции.
Д.К. << RSDN@Home 1.2.0 alpha rev. 655>>
Все на свете должно происходить медленно и неправильно...
Здравствуйте, Аноним, Вы писали:
А>Есть примерно вот такой код (общая идея): А>Как это можно сделать наиболее "легким" способом? А может не стоит огород городить и оставить как есть? Хотелось бы найти наиболее правильное решение. Спасибо.
по моему, так не стоит усложнять, если имеющееся решение Вас устраивает.
по приведенной же ситуации можно сделать вот такие варианты —
enum Type{ one, two, three, four, five };
struct null_type{};
template <typename THead, typename TTail>
struct type_list_node
{
typedef THead head_type;
typedef TTail tail_type;
};
template < Type t >
struct enum_to_type
{
static const Type value = t;
};
template <Type t>
struct Test
{
static bool In( Type forTest )
{
return t == forTest;
}
};
template <Type t1, Type t2>
struct Test2
{
static bool In( Type forTest )
{
return Test<t1>::In(forTest) || Test<t2>::In(forTest);
}
};
template <Type t1, Type t2, Type t3>
struct Test3
{
static bool In( Type forTest )
{
return Test2<t1, t2>::In(forTest) || Test<t3>::In(forTest);
}
};
template <Type t>
struct enum_list1 : type_list_node< enum_to_type<t>, null_type > {};
template <Type t1, Type t2>
struct enum_list2 : type_list_node< enum_to_type<t1>, enum_list1<t2> > {};
template <Type t1, Type t2, Type t3>
struct enum_list3 : type_list_node< enum_to_type<t1>, enum_list2<t2, t3> > {};
template < typename TList >
class tester
{
typedef typename TList::head_type head_type;
typedef typename TList::tail_type tail_type;
template < typename head, typename tail >
struct test_impl
{
static bool in( Type t )
{
return (t == head::value) || tester< tail >::in(t);
}
};
template < typename head >
struct test_impl<head, null_type>
{
static bool in( Type t )
{
return (t == head::value);
}
};
public :
static bool in( Type t )
{
return test_impl< head_type, tail_type >::in(t);
}
};
void test()
{
/* первый вариант */bool b =
Test<one>::In(one)
&& Test2<one, two>::In(two)
&& Test3<one, two, three>::In(three);
/* второй вариант */
b = tester< enum_list1<one> >::in( one );
b = tester< enum_list2<one, two> >::in( one );
b = tester< enum_list3<one, two, three> >::in( four );
return;
}
насколько такие 'огороды' подходят для задачи, решайте сами.
Здравствуйте, _Dreamer, Вы писали:
_D>по моему, так не стоит усложнять, если имеющееся решение Вас устраивает. _D>по приведенной же ситуации можно сделать вот такие варианты — _D>насколько такие 'огороды' подходят для задачи, решайте сами.
Для любителей МосВелосипедСтройМонтажа есть boost/mpl и boost/tuple
А если диапазон перечисления небольшой, то можно и битовые операции задействовать. Тогда не придётся порождать разные воплощения шаблона для разных множеств.
Для желающих — можно всё это запихать внутрь шаблона traits, чтобы всё было типизировано до предела. А заодно и BITSET сделать не встроенным типом, чтоб случайно не смешивать множества и элементы.
Ну и в compile time затащить тоже труда не составит, я думаю.
Здравствуйте, Кодт, Вы писали:
К>Для любителей МосВелосипедСтройМонтажа есть boost/mpl и boost/tuple
Это понятно
Я исходил из того, что, если человек знает о boost/mpl и boost/tuple, то скорее всего, он спросил бы не 'что делать?' а 'что выбрать из следующих вариантов?', как минимум. А то и спрашивать бы не стал.
Поэтому я позволил себе привести идею одного из вариантов решения, естественно, не утверждая что это готовое решение, только вставляй его в код.
Причем как раз без использования сторонних средств вроде буста. Во первых, так мне казалось наглядней, во вторых, думаю так больше шансов, что человек подумает над вариантом, а не просто скопипастит. Естественно, могу быть неправ в своих предположениях.