Like boost::enable_if, but takes a "priority number" and changes overload resolution order

From the Boost documentation: "The enable_if family of templates is a set of tools to allow a function template or a class template specialization to include or exclude itself from a set of matching functions or specializations based on properties of its template arguments."
Sometimes instead of completely excluding a function from overload resolution, I only really want to "tweak" C++'s overload resolution order, or disambiguate an edge case. Instead of relying on C++'s overload priorities, sometimes I'd like to explicitly set the overload priority, like this: template <typename T> void func(boost::overload_priority<1> dummy, ArgType1 arg) {} template <typename T> void func(boost::overload_priority<2> dummy, ArgType2 arg) {} template <typename T> void func(boost::overload_priority<3> dummy, ArgType3 arg) {} Whereas enable_if causes a "hard" error to trigger SFINAE and take a function out of consideration, overload_priority would have some sort of "soft" effect that "tricks" the C++ compiler into thinking it is a less specific match than it is, moving it down in the order of which gets chosen, without actually invalidating it. It isn't obvious that this is even possible, but then, I would never have believed "enable_if" was possible before I heard of it. Whereas enable_if works by wrapping the return type of the function, I believe this would have to wrap a function argument to work. What I have in mind is that the overload_priority class would look like this: template <int N> class overload_priority { public: overload_priority(int x) { ... } }; You would call the overloaded function like this: func(0, the_actual_arg); I'm thinking it would affect the overload priority by some trick like causing an N-deep nested conversion sequence (overload_priority<3> constructed from overload_priority<2>, from overload_priority<1>, from the integer 0) or by the constructor having N extra parameters with default arguments. Any comments or ideas for improving this?

AMDG Dennis Ferron wrote:
From the Boost documentation: "The enable_if family of templates is a set of tools to allow a function template or a class template specialization to include or exclude itself from a set of matching functions or specializations based on properties of its template arguments."
Sometimes instead of completely excluding a function from overload resolution, I only really want to "tweak" C++'s overload resolution order, or disambiguate an edge case. Instead of relying on C++'s overload priorities, sometimes I'd like to explicitly set the overload priority, like this:
template <typename T> void func(boost::overload_priority<1> dummy, ArgType1 arg) {}
template <typename T> void func(boost::overload_priority<2> dummy, ArgType2 arg) {}
template <typename T> void func(boost::overload_priority<3> dummy, ArgType3 arg) {}
Whereas enable_if causes a "hard" error to trigger SFINAE and take a function out of consideration, overload_priority would have some sort of "soft" effect that "tricks" the C++ compiler into thinking it is a less specific match than it is, moving it down in the order of which gets chosen, without actually invalidating it. It isn't obvious that this is even possible, but then, I would never have believed "enable_if" was possible before I heard of it. Whereas enable_if works by wrapping the return type of the function, I believe this would have to wrap a function argument to work. What I have in mind is that the overload_priority class would look like this:
template <int N> class overload_priority { public: overload_priority(int x) { ... } };
You would call the overloaded function like this:
func(0, the_actual_arg);
I'm thinking it would affect the overload priority by some trick like causing an N-deep nested conversion sequence (overload_priority<3> constructed from overload_priority<2>, from overload_priority<1>, from the integer 0) or by the constructor having N extra parameters with default arguments.
C++ only allows a single user defined conversion in a conversion sequence. You'd have to use many levels of inheritance. template<int N> struct overload_priority : overload_priority<N+1> {}; // base case template<> struct overload_priority<16> {}; func((overload_priority<0>*)0, ...);
Any comments or ideas for improving this?
In Christ, Steven Watanabe
participants (2)
-
Dennis Ferron
-
Steven Watanabe