enable_if and multiple partial specializations

Hi,
It's late and I might be missing something, but I can't figure out how can I use
enable_if to disambiguate 2 partial specializations where one is subcase of
another one:
#include

On 08/04/11 10:59, Gennadiy Rozental wrote:
Hi,
It's late and I might be missing something, but I can't figure out how can I use enable_if to disambiguate 2 partial specializations where one is subcase of another one:
#include
#include #include #include<iostream>
template
struct M { static void foo() { std::cout<< "generic"<< std::endl; } }; template<typename T> struct M
::type> { static void foo() { std::cout<< "scalar"<< std::endl; } }; template<typename T> struct M
::type> { static void foo() { std::cout<< "enum"<< std::endl; } };
M<FOO>::foo() fails to compile due to ambiguity.
Any pointers? Or How to get what I want?
enum are scalar so :
template<class T>
struct M

Joel Falcou
template<class T> struct M
::type> { static void foo() { std::cout<< "enum"<< std::endl; } }; template<typename T> struct M
::type> { static void foo() { std::cout<< "scalar"<< std::endl; } };
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? Thank you, Gennadiy

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.

On Fri, Apr 8, 2011 at 11:04 AM, Joel Falcou
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
::type type; };
template<typename T> struct M_impl;
template<>
struct M_impl

Stirling Westrup
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
#include #include #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
{ static void foo() { std::cout << "generic" << std::endl; } }; template<> struct M_impl
{ static void foo() { std::cout << "scalar" << std::endl; } }; template<> struct M_impl
{ static void foo() { std::cout << "enum" << std::endl; } };
This has at least 2 problems: 1. It does not work. I need "scalar" level specialization to be applied if enum level specialization is not present. In your case it will not even compile. Or it will choose incorrect (generic) option if you non specialized version for that. We can try to follow STL's approach of iterator tag dispatching based on hierarhy, but that really cumbersome and require extra runtime wrappers. 2. It's intrusive. Once I introduce new subgroup of types I need to go in common header and update tag selection (and potentially something else to handle relation with other groups) That's said I did not come up with something better yet. Gennadiy

On 09/04/11 05:14, Gennadiy Rozental wrote:
This has at least 2 problems:
1. It does not work. I need "scalar" level specialization to be applied if enum level specialization is not present. In your case it will not even compile. Or it will choose incorrect (generic) option if you non specialized version for that. We can try to follow STL's approach of iterator tag dispatching based on hierarhy, but that really cumbersome and require extra runtime wrappers.
I can be doen using compile-time stuff, no need for runtime.
2. It's intrusive. Once I introduce new subgroup of types I need to go in common header and update tag selection (and potentially something else to handle relation with other groups)
We faced this exact same problem in NT2 and we ended up having a whole component dedicated to complex, multiple arguments, hierarchical traits dispatching. This is a non trivial problem and it gets out of hand fast once you want to add new types familly and still be extensible. Our solution rely on having a "hierarchy" traits defined for types and use operator overload detection meta-function to select the proper hierarchy from : the actual type and the actual existence of an overload. We use this exact system in our SIMD library, so it may be of interest to make it a proper reusable component.

On Fri, Apr 8, 2011 at 9:59 AM, Gennadiy Rozental
Hi,
It's late and I might be missing something, but I can't figure out how can I use enable_if to disambiguate 2 partial specializations where one is subcase of another one:
#include
#include #include #include <iostream>
template
struct M { static void foo() { std::cout << "generic" << std::endl; } }; template<typename T> struct M
::type> { static void foo() { std::cout << "scalar" << std::endl; } }; template<typename T> struct M
::type> { static void foo() { std::cout << "enum" << std::endl; } }; struct S {}; enum FOO { FOO1, FOO2 };
int main() { M<S>::foo(); M<int>::foo(); M<FOO>::foo(); }
---------------
M<FOO>::foo() fails to compile due to ambiguity.
Any pointers? Or How to get what I want?
I'm assuming the problem is that the scalar case is also true for the enum case? On that basis, could you not us an enabler that asks if it is scalar && ! enum? - Rob. (That's just off the cuff - I 'spect a proper expert will be along soon!)
participants (4)
-
Gennadiy Rozental
-
Joel Falcou
-
Robert Jones
-
Stirling Westrup