можно ли такое на шаблонах провернуть...
Привет!
значит есть вот что:
enum some_enum { en1, en2, en3 };
void foo(some_enum e) {...}
в зависимости от значения параметра foo ведет себя совершенно по разному (т.е. банальный switch)
void foo(some_enum e)
{
swith (e) {
case en1: foo_en1_implementation(); break ;
...
default : throw not_implemented;
}
}
не люблю писать switch принципильно
поэтому делаю так:
enum some_enum { en1, en2, en3 };
template <some_enum>
void foo()
{
std::cout << "unspecified" << std::endl;
}
template <>
void foo<en1>()
{
std::cout << "en1 implementation" << std::endl;
}
int main()
{
foo<en1>();
foo<en2>();
return 0;
}
все как бы работает... но как-то некрасиво писать foo
<en1> ()
хочется вот так:
foo(en1); // но внутри swithc не писать
Возможно ли такое сотворить ?
ЗЫ: никакого runtime не будет... foo будет вызываться только так foo(/*en1 | en2 | en3*/) т.е. компилятор точно знает значение передаваемого аргумента
<b>bold text</b>
Re: можно ли такое на шаблонах провернуть...
Здравствуйте, ламмму, Вы писали:
[]
Л>Л>enum some_enum { en1, en2, en3 };
Л>template <some_enum>
Л>void foo( some_enum se )
Л>{
Л> std::cout << "unspecified" << std::endl;
Л>}
Л>template <>
Л>void foo<en1>( some_enum se )
Л>{
Л> std::cout << "en1 implementation" << std::endl;
Л>}
Л>int main()
Л>{
Л> foo(en1);
Л> foo(en2);
Л> return 0;
Л>}
Л>
Re[2]: можно ли такое на шаблонах провернуть...
не выйдет
Of course, the code must be complete enough to compile and link .
Re: можно ли такое на шаблонах провернуть...
От:
rg45
Дата: 20.12.06 14:16
Оценка:
" ламмму " <44993@users.rsdn.ru> wrote in message
news:2273029@news.rsdn.ru ...
> Привет!
> значит есть вот что:
> > enum some_enum { en1, en2, en3 };
> void foo(some_enum e) {...}
>
> в зависимости от значения параметра foo ведет себя совершенно по разному (т.е. банальный switch)
> > void foo(some_enum e)
> {
> swith (e) {
> case en1: foo_en1_implementation(); break ;
> ...
> default : throw not_implemented;
> }
> }
>
> не люблю писать switch принципильно поэтому делаю так:
> > enum some_enum { en1, en2, en3 };
>
> template <some_enum>
> void foo()
> {
> std::cout << "unspecified" << std::endl;
> }
>
> template <>
> void foo<en1>()
> {
> std::cout << "en1 implementation" << std::endl;
> }
>
> int main()
> {
> foo<en1>();
> foo<en2>();
>
> return 0;
> }
>
> все как бы работает... но как-то некрасиво писать foo<en1> ()
> хочется вот так:
> foo(en1); // но внутри swithc не писать
> Возможно ли такое сотворить ?
>
> ЗЫ: никакого runtime не будет... foo будет вызываться только так foo(/*en1 | en2 | en3*/) т.е. компилятор точно знает значение передаваемого аргумента
Можно, но только en1, en2, en3 нужно сделать шаблоными параметрами:
#include <iostream>
#define TRACE std::cout << __FUNCSIG__ << std::endl;
enum some_enum { en1, en2, en3 };
//Общее объявление шаблонной функции
template <some_enum> void foo();
//А далше идут конкретные специализации
template <> void foo<en1>() {TRACE}
template <> void foo<en2>() {TRACE}
template <> void foo<en3>() {TRACE}
int main()
{
foo<en1>();
foo<en2>();
foo<en3>();
}
Posted via RSDN NNTP Server 2.0
--
C++ уже затем учить надо, что он ум в порядок приводит. (с) Ломоносов М.В.
Re[2]: можно ли такое на шаблонах провернуть...
От:
rg45
Дата: 20.12.06 14:20
Оценка:
"rg45" <49596@users.rsdn.ru> wrote in message
news:2273110@news.rsdn.ru ...
>
Не дочитал пост до конца и посоветовал то, что автор знал и так, сорри
Posted via RSDN NNTP Server 2.0
--
C++ уже затем учить надо, что он ум в порядок приводит. (с) Ломоносов М.В.
Re: можно ли такое на шаблонах провернуть...
Здравствуйте, ламмму, Вы писали:
Л>все как бы работает... но как-то некрасиво писать foo<en1> ()
Л>хочется вот так:
Л>foo(en1); // но внутри swithc не писать
Л>Возможно ли такое сотворить ?
struct en1 { enum { value = 0 }; } en1;
struct en2 { enum { value = 1 }; } en2;
struct en3 { enum { value = 2 }; } en3;
struct en4 { enum { value = 2 }; } en4;
template <typename T>
void foo(T)
{
std::cout << "unspecified" << std::endl;
}
void foo(struct en1)
{
std::cout << "en1 implementation" << std::endl;
}
void foo(struct en2)
{
std::cout << "en1 implementation" << std::endl;
}
void foo(struct en3)
{
std::cout << "en1 implementation" << std::endl;
}
int main()
{
foo(en1);
foo(en2);
foo(en3);
foo(en4);
}
Минусы думаю на лицо.
Re[2]: можно ли такое на шаблонах провернуть...
Здравствуйте, Pavel Chikulaev, Вы писали:
PC>PC>struct en1 { enum { value = 0 }; } en1;
PC>struct en2 { enum { value = 1 }; } en2;
PC>struct en3 { enum { value = 2 }; } en3;
PC>struct en4 { enum { value = 2 }; } en4;
PC>
Упс, лучше так:
PC>struct en1 { enum { value = 0 }; } const en1;
PC>struct en2 { enum { value = 1 }; } const en2;
PC>struct en3 { enum { value = 2 }; } const en3;
PC>struct en4 { enum { value = 2 }; } const en4;
Re[3]: можно ли такое на шаблонах провернуть...
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>не выйдет
угу
Re: можно ли такое на шаблонах провернуть...
От:
Sm0ke
ksi
Дата: 20.12.06 14:53
Оценка:
Здравствуйте, ламмму, Вы писали:
Л>Привет!
Л>значит есть вот что:
Л>Л>enum some_enum { en1, en2, en3 };
Л>void foo(some_enum e) {...}
Л>
Л>в зависимости от значения параметра foo ведет себя совершенно по разному (т.е. банальный switch)
Л>Л>void foo(some_enum e)
Л>{
Л> swith (e) {
Л> case en1: foo_en1_implementation(); break ;
Л> ...
Л> default : throw not_implemented;
Л> }
Л>}
Л>
Л>не люблю писать switch принципильно поэтому делаю так:
Л>Л>enum some_enum { en1, en2, en3 };
Л>template <some_enum>
Л>void foo()
Л>{
Л> std::cout << "unspecified" << std::endl;
Л>}
Л>template <>
Л>void foo<en1>()
Л>{
Л> std::cout << "en1 implementation" << std::endl;
Л>}
Л>int main()
Л>{
Л> foo<en1>();
Л> foo<en2>();
Л> return 0;
Л>}
Л>
Л>все как бы работает... но как-то некрасиво писать foo<en1> ()
Л>хочется вот так:
Л>foo(en1); // но внутри swithc не писать
Л>Возможно ли такое сотворить ?
Л>ЗЫ: никакого runtime не будет... foo будет вызываться только так foo(/*en1 | en2 | en3*/) т.е. компилятор точно знает значение передаваемого аргумента
Можно сделать массив ф-йций:
enum some_enum { en1, en2, en3 };
template <some_enum>
void foo()
{
std::cout << "unspecified" << std::endl;
}
template <>
void foo<en1>()
{
std::cout << "en1 implementation" << std::endl;
}
typedef void (*hfn)(some_enum);
hfn foo_array[] =
{
&foo<en1>,
&foo<en2>,
&foo<en3>
};
inline void foo(some_enum se)
{
return foo_array[se]();
}
void main()
{
foo_array[en1]();
foo(en2);
}
а можно через Loki::Typelist
#include "Loki/HierarchyGenerators.h"
enum some_enum { en1, en2, en3 };
template <some_enum>
void foo()
{
std::cout << "unspecified" << std::endl;
}
template <>
void foo<en1>()
{
std::cout << "en1 implementation" << std::endl;
}
template <class Enum, Enum Value>
struct Enum2Type
{
typedef Enum type;
};
template <class ResultType>
struct helper
{
template <class T, class B>
class unit;
template <class Enum, Enum SE, class B>
class unit<Enum2Type<Enum, SE>, B> : public B
{
protected :
static ResultType unit_call(some_enum se)
{
if (se == SE) return foo<SE>();
return B::unit_call(se);
}
};
template <class Enum, Enum SE>
class unit<Enum2Type<Enum, SE>, Loki::EmptyType>
{
protected :
static ResultType unit_call(some_enum se)
{
return foo<SE>();
}
};
};
struct cfoo : Loki::GenLinearHierarchy
<
Loki::TL::MakeTypelist
<
Enum2Type<some_enum, en1>,
Enum2Type<some_enum, en2>,
Enum2Type<some_enum, en3>
>::Result,
helper<void >::unit
>
{
static void call(some_enum se)
{
return unit_call(se);
}
};
int _tmain()
{
/*foo<en1>();
foo<en2>();*/
cfoo::call(tmp10::en1);
cfoo::call(tmp10::en2);
return 0;
}
Re[2]: можно ли такое на шаблонах провернуть...
От:
Sm0ke
ksi
Дата: 20.12.06 14:57
Оценка:
а можно через Loki::Typelist
#include "Loki/HierarchyGenerators.h"
enum some_enum { en1, en2, en3 };
template <some_enum>
void foo()
{
std::cout << "unspecified" << std::endl;
}
template <>
void foo<en1>()
{
std::cout << "en1 implementation" << std::endl;
}
template <class Enum, Enum Value>
struct Enum2Type
{
typedef Enum type;
};
template <class ResultType>
struct helper
{
template <class T, class B>
class unit;
template <class Enum, Enum SE, class B>
class unit<Enum2Type<Enum, SE>, B> : public B
{
protected :
static ResultType unit_call(some_enum se)
{
if (se == SE) return foo<SE>();
return B::unit_call(se);
}
};
template <class Enum, Enum SE>
class unit<Enum2Type<Enum, SE>, Loki::EmptyType>
{
protected :
static ResultType unit_call(some_enum se)
{
return foo<SE>();
}
};
};
struct cfoo : Loki::GenLinearHierarchy
<
Loki::TL::MakeTypelist
<
Enum2Type<some_enum, en1>,
Enum2Type<some_enum, en2>,
Enum2Type<some_enum, en3>
>::Result,
helper<void >::unit
>
{
static void call(some_enum se)
{
return unit_call(se);
}
};
int _tmain()
{
/*foo<en1>();
foo<en2>();*/
cfoo::call(en1); // забыл убрать namespace
cfoo::call(en2);
return 0;
}
Re: можно ли такое на шаблонах провернуть...
От:
Spin_
Дата: 20.12.06 15:09
Оценка:
+1
Здравствуйте, ламмму, Вы писали:
Л>Привет!
Л>значит есть вот что:
Л>Л>enum some_enum { en1, en2, en3 };
Л>void foo(some_enum e) {...}
Л>
Л>в зависимости от значения параметра foo ведет себя совершенно по разному (т.е. банальный switch)
Л>Л>void foo(some_enum e)
Л>{
Л> swith (e) {
Л> case en1: foo_en1_implementation(); break ;
Л> ...
Л> default : throw not_implemented;
Л> }
Л>}
Л>
Л>не люблю писать switch принципильно поэтому делаю так:
Л>Л>enum some_enum { en1, en2, en3 };
Л>template <some_enum>
Л>void foo()
Л>{
Л> std::cout << "unspecified" << std::endl;
Л>}
Л>template <>
Л>void foo<en1>()
Л>{
Л> std::cout << "en1 implementation" << std::endl;
Л>}
Л>int main()
Л>{
Л> foo<en1>();
Л> foo<en2>();
Л> return 0;
Л>}
Л>
Л>все как бы работает... но как-то некрасиво писать foo<en1> ()
Л>хочется вот так:
Л>foo(en1); // но внутри swithc не писать
Л>Возможно ли такое сотворить ?
Л>ЗЫ: никакого runtime не будет... foo будет вызываться только так foo(/*en1 | en2 | en3*/) т.е. компилятор точно знает значение передаваемого аргумента
Можно и так:
enum Enum { en1, en2, en3 };
template <int i> struct IntWrapper {
enum { value = i };
};
void f_impl(IntWrapper<en1> obj) {printf("En1\n" );}
void f_impl(IntWrapper<en2> obj) {printf("En2\n" );}
void f_impl(IntWrapper<en3> obj) {printf("En3\n" );}
#define f(obj) f_impl(IntWrapper<obj>())
int main() {
f(en1);
f(en2);
f(en3);
return 0;
}
Re[2]: можно ли такое на шаблонах провернуть...
От:
shank
Дата: 20.12.06 15:29
Оценка:
Здравствуйте, Spin_, Вы писали:
S_>Можно и так:
S_>S_>enum Enum { en1, en2, en3 };
S_>template <int i> struct IntWrapper {
S_> enum { value = i };
S_>};
S_>void f_impl(IntWrapper<en1> obj) {printf("En1\n" );}
S_>void f_impl(IntWrapper<en2> obj) {printf("En2\n" );}
S_>void f_impl(IntWrapper<en3> obj) {printf("En3\n" );}
S_>#define f(obj) f_impl(IntWrapper<obj>())
S_>int main() {
S_> f(en1);
S_> f(en2);
S_> f(en3);
S_> return 0;
S_>}
S_>
Если юзать макросы, то имхо проще в исходном коде сделать просто
#define call_foo(X) foo<X>()
и вызывать
call_foo(en1);
call_foo(en2);
Re: можно ли такое на шаблонах провернуть...
Здравствуйте, ламмму, Вы писали:
Л>Привет!
Л>int main()
Л>{
Л> foo<en1>();
Л> foo<en2>();
Л> return 0;
Л>}
ИМХО если значения enuma меняются в рантайме, то шаблоны тут не причем и надо юзать свитч/виртуальные методы, а если всё зашито на этапе компиляции, то
foo_en1(); foo_en2(); — рулят однозначно, хотя бы из-за упрощения кода и нормального кодекомплишена.
PS читать Александреску надо в меру и не увлекаться!
Re[2]: можно ли такое на шаблонах провернуть...
От:
dotidot
Дата: 20.12.06 16:17
Оценка:
Здравствуйте, dotidot, Вы писали:
D> enuma меняются в рантайме,
я, конечно, имел ввиду не значения элементов самого enumа, а аргумент функции/шаблона.
Re: можно ли такое на шаблонах провернуть...
Здравствуйте, ламмму, Вы писали:
using boost::mpl::int_;
enum some_enum { en1, en2, en3 };
void foo(boost::mpl::int_<en1>) {}
void foo(boost::mpl::int_<en2>) {}
void foo(boost::mpl::int_<en3>) {}
int main()
{
foo(int_<en1>());
foo(int_<en2>());
foo(int_<en3>());
}
Re: можно ли такое на шаблонах провернуть...
Здравствуйте, ламмму, Вы писали:
А что мешает написать просто:
void foo_en1() {}
void foo_en2() {}
void foo_en3() {}
int main()
{
foo_en1();
foo_en2();
foo_en3();
}
Re[2]: можно ли такое на шаблонах провернуть...
От:
dotidot
Дата: 20.12.06 22:20
Оценка:
Здравствуйте, remark, Вы писали:
R>Здравствуйте, ламмму, Вы писали:
R>А что мешает написать просто:
R>R>void foo_en1() {}
R>void foo_en2() {}
R>void foo_en3() {}
R>int main()
R>{
R> foo_en1();
R> foo_en2();
R> foo_en3();
R>}
R>
Плагиат!
Re[3]: можно ли такое на шаблонах провернуть...
Да, вариант с локи тайплистом наиболее оптимален по объему кода, нужного для решения этой вселенской проблемы. А то прям смех — на хаскеле люди пишут интерпретатор подмножества лиспа в 180 строк, а мы тут просто switch нагрохаем в 500. Зашибись
)
Of course, the code must be complete enough to compile and link .
Re[4]: можно ли такое на шаблонах провернуть...
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить