Boost logo

Boost Users :

Subject: Re: [Boost-users] enable_if and multiple partial specializations
From: Stirling Westrup (swestrup_at_[hidden])
Date: 2011-04-08 13:12:59


On Fri, Apr 8, 2011 at 11:04 AM, Joel Falcou <joel.falcou_at_[hidden]> wrote:
> On 08/04/11 17:05, Gennadiy Rozental wrote:
>>
>> This will not really work for me. This was just an artificial example. In
>> reality I have generic header which defines the template, another common
>> header which defines some not very specific specialization and multiple (number
>> changes as project grows) headers where I define more specific specializations. I
>> can't "NOT" all the specific conditions in "scalar" level specialization - It's
>> just not maintainable.
>>
>> Any other options?
>
> - have a first level function enable_if on the highest catching metafunction
> then do tag dispatching inside to other function enabled_if on
> specialization of said initial test.
>
> - build sensible, non overlapping traits for your cases and use these
> instead of raw type traits.
>
> enable_if cant work with overlapping conditions.

This suggestion really is your best bet. To elaborate a bit further,
you don't really even want to use enable_if in this case. You really
want to write something like:

#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_scalar.hpp>

#include <iostream>

struct tag_other{};
struct tag_scalar{};
struct tag_enum : tag_scalar{};

// there are many better ways of writing tag_lookup.
// This is just an example.
template<typename T>
struct tag_lookup {
  typedef typename boost::mpl::if_<
    boost::is_scalar<T>,
      typename boost::mpl::if_<
        boost::is_enum<T>, tag_enum, tag_scalar
>::type, tag_other
>::type type;
};

template<typename T> struct M_impl;

template<>
struct M_impl<tag_other> {
   static void foo() { std::cout << "generic" << std::endl; }
};

template<>
struct M_impl<tag_scalar> {
   static void foo() { std::cout << "scalar" << std::endl; }
};

template<>
struct M_impl<tag_enum> {
   static void foo() { std::cout << "enum" << std::endl; }
};

template<typename T>
struct M : M_impl< typename tag_lookup<T>::type >
{};

struct S {};
enum FOO { FOO1, FOO2 };

int main()
{
   M<S>::foo();
   M<int>::foo();
   M<FOO>::foo();
}

-- 
Stirling Westrup
Programmer, Entrepreneur.
https://www.linkedin.com/e/fpf/77228
http://www.linkedin.com/in/swestrup
http://technaut.livejournal.com
http://sourceforge.net/users/stirlingwestrup

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net