можно ли такое на шаблонах провернуть...
От: ламмму Украина http://itjob.kharkov.ua
Дата: 20.12.06 13:43
Оценка:
Привет!
значит есть вот что:
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: можно ли такое на шаблонах провернуть...
От: Константин Л. Франция  
Дата: 20.12.06 13:47
Оценка:
Здравствуйте, ламмму, Вы писали:

[]

Л>
Л>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]: можно ли такое на шаблонах провернуть...
От: Lorenzo_LAMAS  
Дата: 20.12.06 14:05
Оценка: +1
не выйдет
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
--
Не можешь достичь желаемого — пожелай достигнутого.
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
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: можно ли такое на шаблонах провернуть...
От: Pavel Chikulaev Россия  
Дата: 20.12.06 14:23
Оценка: +1
Здравствуйте, ламмму, Вы писали:

Л>все как бы работает... но как-то некрасиво писать 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 Россия  
Дата: 20.12.06 14:25
Оценка:
Здравствуйте, 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]: можно ли такое на шаблонах провернуть...
От: Константин Л. Франция  
Дата: 20.12.06 14:27
Оценка:
Здравствуйте, 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: можно ли такое на шаблонах провернуть...
От: dotidot Россия  
Дата: 20.12.06 16:14
Оценка: 11 (2) +1
Здравствуйте, ламмму, Вы писали:

Л>Привет!

Л>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: можно ли такое на шаблонах провернуть...
От: remark Россия http://www.1024cores.net/
Дата: 20.12.06 19:41
Оценка:
Здравствуйте, ламмму, Вы писали:



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>());
}





1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: можно ли такое на шаблонах провернуть...
От: remark Россия http://www.1024cores.net/
Дата: 20.12.06 19:42
Оценка: 1 (1)
Здравствуйте, ламмму, Вы писали:

А что мешает написать просто:

void foo_en1() {}
void foo_en2() {}
void foo_en3() {}

int main()
{
  foo_en1();
  foo_en2();
  foo_en3();
}




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
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]: можно ли такое на шаблонах провернуть...
От: Lorenzo_LAMAS  
Дата: 21.12.06 09:09
Оценка: 1 (1) +1 :)))
Да, вариант с локи тайплистом наиболее оптимален по объему кода, нужного для решения этой вселенской проблемы. А то прям смех — на хаскеле люди пишут интерпретатор подмножества лиспа в 180 строк, а мы тут просто switch нагрохаем в 500. Зашибись )

Of course, the code must be complete enough to compile and link.
Re[4]: можно ли такое на шаблонах провернуть...
От: remark Россия http://www.1024cores.net/
Дата: 21.12.06 11:51
Оценка: :))
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Да, вариант с локи тайплистом наиболее оптимален по объему кода, нужного для решения этой вселенской проблемы. А то прям смех — на хаскеле люди пишут интерпретатор подмножества лиспа в 180 строк, а мы тут просто switch нагрохаем в 500. Зашибись )


Ты не понимаешь! Функционал — уже не главное

L_L>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.