Interest in switch generator

AMDG Is there any interest in a function template that generates a switch statement? struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } }; int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} } In Christ, Steven Watanabe

Hi Steven! On 2/3/07, Steven Watanabe <steven@providere-consulting.com> wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
I've been working on something pretty similar, but is dynamic and can use not only int's as the "indexes". More information at http://dispatcher.sourceforge.net/ . I'm currently in the process of cleaning up the implementation using Boost.PP, but there's already stuff there that's usable for a "switch replacement" scenario. HTH! -- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459

AMDG Dean Michael Berris <mikhailberis <at> gmail.com> writes:
Hi Steven!
On 2/3/07, Steven Watanabe <steven <at> providere-consulting.com> wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
I've been working on something pretty similar, but is dynamic and can use not only int's as the "indexes". More information at http://dispatcher.sourceforge.net/ .
I'm currently in the process of cleaning up the implementation using Boost.PP, but there's already stuff there that's usable for a "switch replacement" scenario.
HTH!
My purpose was to get all the perfomance of a built in switch in a way that is usable in generic contexts. Thus, I am using the preprocessor to generate a real switch statement. A dynamic dispatcher is nice but it isn't really the same thing. In Christ, Steven Watanabe

On 2/3/07, Steven Watanabe <steven@providere-consulting.com> wrote:
AMDG
Dean Michael Berris <mikhailberis <at> gmail.com> writes:
I've been working on something pretty similar, but is dynamic and can use not only int's as the "indexes". More information at http://dispatcher.sourceforge.net/ .
I'm currently in the process of cleaning up the implementation using Boost.PP, but there's already stuff there that's usable for a "switch replacement" scenario.
HTH!
My purpose was to get all the perfomance of a built in switch in a way that is usable in generic contexts. Thus, I am using the preprocessor to generate a real switch statement. A dynamic dispatcher is nice but it isn't really the same thing.
Ah, yes. My bad. I'd love to be able to use something like this in my implementation too, so yes I'm interested as well. :-) -- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459

Hello Steven, Friday, February 2, 2007, 10:16:54 PM, you wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } };
int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} }
Interesting. It would be much better if it is integrated with Boost.Lambda. Something like this: switch_< cases >(5, var(cout) << "2\n", var(cout) << "1\n", var(cout) << "0\n", var(cout) << "default case - may be optional\n" ); In fact, it would be even greater to extend the language switch capabilities to type-selection and non-integral type constants with fusion containers or tuples. Something like: typedef fusion::vector< int, int, string, double > cases_t; cases_t cases(2, 5, "a string", 7.3); list< any > container1; // assume it's filled for_each(container1.begin(), container1.end(), switch_(_1, cases, var(cout) << "The value is int and equals 2\n", var(cout) << "The value is int and equals 5\n", var(cout) << "The value is string 'a string'\n", var(cout) << "The value is double and equals 7.3\n", var(cout) << "The default branch\n"); vector< int > container2; // assume it's filled for_each(container2.begin(), container2.end(), switch_(_1, cases, var(cout) << "The value is int and equals 2\n", var(cout) << "The value is int and equals 5\n"); // other cases are not significant since they won't happen -- Best regards, Andrey mailto:andysem@mail.ru

Andrey Semashev wrote:
Hello Steven,
Friday, February 2, 2007, 10:16:54 PM, you wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } };
int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} }
Interesting. It would be much better if it is integrated with Boost.Lambda. Something like this:
Phoenix2 provides this functionality. Regards, Tobias

Hi Steven, Steven Watanabe wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
Yes. I'm interested.
struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } };
int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} }
Is this an interface proposal or just some code to illustrate the idea? I'd like to have templatized parameters and probably separate function objects for the cases rather than shape-shifting overloads... Regards, Tobias

Tobias Schwinger <tschwinger <at> isonews2.com> writes:
Hi Steven,
Steven Watanabe wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
Yes. I'm interested.
struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } };
int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} }
Is this an interface proposal or just some code to illustrate the idea?
Yes this was how the interface would look. I also have a three parameter version to handle default
I'd like to have templatized parameters and probably separate function objects for the cases rather than shape-shifting overloads...
I did it this way to allow usage like template<class FusionSequence> struct print_nth { template<class Index> void operator()(Index) const { std::cout << fusion::at<Index>(sequence) << std::endl; } print_nth(const FusionSequence& s) : sequence(s) {} const FusionSequence& sequence; };
Regards, Tobias

Steven Watanabe <steven <at> providere-consulting.com> writes: I just uploaded the implementation to the vault. In Christ, Steven Watanabe

Hello Steven, Saturday, February 3, 2007, 6:26:37 AM, you wrote:
Steven Watanabe <steven <at> providere-consulting.com> writes:
I just uploaded the implementation to the vault.
Maybe throw_exception.hpp should be used to actually throw exceptions. And maybe a good idea is to pass an actual value that triggered the default handler in the exception object. I'm not sure why do you consider such use case invalid: void empty_default(int); switch_< cases >(1, f, &empty_default); IMHO, the intent is quite clear - to call empty_default as the default handler. But the following: switch_(1, f, &empty_default); will not compile since V may not be deduced. Am I missing something? -- Best regards, Andrey mailto:andysem@mail.ru

Andrey Semashev <andysem <at> mail.ru> writes:
Hello Steven,
Saturday, February 3, 2007, 6:26:37 AM, you wrote:
Steven Watanabe <steven <at> providere-consulting.com> writes:
I just uploaded the implementation to the vault.
Maybe throw_exception.hpp should be used to actually throw exceptions. And maybe a good idea is to pass an actual value that triggered the default handler in the exception object.
Will do.
I'm not sure why do you consider such use case invalid:
void empty_default(int); switch_< cases >(1, f, &empty_default);
I don't
IMHO, the intent is quite clear - to call empty_default as the default handler. But the following:
switch_(1, f, &empty_default);
will not compile since V may not be deduced. Am I missing something?
I meant using wrap as opposed to a raw pointer to V. see http://www.boost.org/libs/config/config.htm#helpers under BOOST_EXPLICIT_TEMPLATE_TYPE. Oh. It already handles this case I'll fix it to use BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE In Christ, Steven Watanabe

AMDG Andrey Semashev <andysem <at> mail.ru> writes:
And maybe a good idea is to pass an actual value that triggered the default handler in the exception object.
Do you think I should store the value as an integer or lexical_cast it to a string and pass it to the constructor of std::runtime_error? If I store it as an integer, no matter what type I use, it could overflow. In Christ, Steven Watanabe

Hello Steven, Sunday, February 4, 2007, 1:02:12 AM, you wrote:
AMDG
Andrey Semashev <andysem <at> mail.ru> writes:
And maybe a good idea is to pass an actual value that triggered the default handler in the exception object.
Do you think I should store the value as an integer or lexical_cast it to a string and pass it to the constructor of std::runtime_error? If I store it as an integer, no matter what type I use, it could overflow.
I think the value should be in the error message. But you also can store it as intmax_t value in the exception. I think, this would be sufficient for 99% cases. -- Best regards, Andrey mailto:andysem@mail.ru

AMDG Andrey Semashev <andysem <at> mail.ru> writes:
I think the value should be in the error message. But you also can store it as intmax_t value in the exception. I think, this would be sufficient for 99% cases.
What if I am passed a uintmax_t? I think I'll just put it in the error message. Thank you for your feedback. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Is there any interest in a function template that generates a switch statement?
struct f { typedef void result_type; void operator()(mpl::int_<0>) const { std::cout << "2" << std::endl; } void operator()(mpl::int_<1>) const { std::cout << "1" << std::endl; } void operator()(mpl::int_<5>) const { std::cout << "0" << std::endl; } };
int main() { typedef mpl::vector<mpl::int_<0>, mpl::int_<1>, mpl::int_<5> > cases; switch<cases>(5, f()); //prints 0 try { switch<cases>(3, f()); } catch(bad_switch&) {} }
I'm interested. I'll need polymorphic return type handling though. Something like: struct f { template <typename Case> struct result; template <> struct result<mpl::int_<0> > : mpl::identity<char> {}; template <> struct result<mpl::int_<2> > : mpl::identity<float> {}; template <> struct result<mpl::int_<5> > : mpl::identity<std::string> {}; char operator()(mpl::int_<0>) const; float operator()(mpl::int_<1>) const; std::string operator()(mpl::int_<5>) const; }; Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

AMDG Joel de Guzman <joel <at> boost-consulting.com> writes:
I'm interested. I'll need polymorphic return type handling though. Something like:
struct f { template <typename Case> struct result;
template <> struct result<mpl::int_<0> > : mpl::identity<char> {};
template <> struct result<mpl::int_<2> > : mpl::identity<float> {};
template <> struct result<mpl::int_<5> > : mpl::identity<std::string> {};
char operator()(mpl::int_<0>) const; float operator()(mpl::int_<1>) const; std::string operator()(mpl::int_<5>) const; };
Regards,
So what goes here? template<class Cases, class Int, class F> ??? switch_(Int i, F f); ??? could be either any or variant. If any, why then, typedef boost::any result_type works just fine. Variant is a little more difficult especially if operator() is a template. template<class F> struct get_result { template<class Case> struct apply { typedef typename F::template result<Case>::type type; }; }; template<class F, class Sequence> struct variant_adapter : F { typedef typename mpl::transform<Sequence, mpl::protect<get_result<F> >, mpl::inserter<mpl::set0<>, mpl::insert<_1, _2> > >::type possible_results; typedef typename make_variant_over<possible_results>::type result_type; variant_adapter(const F& f) : F(f) {} }; In Christ, Steven Watanabe

Steven Watanabe wrote:
I'm interested. I'll need polymorphic return type handling though. Something like:
struct f { template <typename Case> struct result;
template <> struct result<mpl::int_<0> > : mpl::identity<char> {};
template <> struct result<mpl::int_<2> > : mpl::identity<float> {};
template <> struct result<mpl::int_<5> > : mpl::identity<std::string> {};
char operator()(mpl::int_<0>) const; float operator()(mpl::int_<1>) const; std::string operator()(mpl::int_<5>) const; };
Regards,
So what goes here?
template<class Cases, class Int, class F> ??? switch_(Int i, F f);
??? could be either any or variant. If any, why then, typedef boost::any result_type works just fine. Variant is a little more difficult especially if operator() is a template.
Yeah, right. That's too hairy. I guess it's best to have that (variant returns) as the responsibility of the function object: struct f { typedef variant<char, float, std::string> result_type; char operator()(mpl::int_<0>) const; float operator()(mpl::int_<1>) const; std::string operator()(mpl::int_<5>) const; }; Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
participants (5)
-
Andrey Semashev
-
Dean Michael Berris
-
Joel de Guzman
-
Steven Watanabe
-
Tobias Schwinger