How to make function template least prioritized during ADL?

I have a problem when I would like to provide a generic version of the function foo , which can only be applied when there is no other match for the call. How to change the following code so that last_resort::foo matches worse with derived::type than base::foo ? I would like to find a solution that does not include modifying the definition of bar and which will keep the argument type last_resort::foo .

 #include <iostream> namespace last_resort { template<typename T> void foo(T) { std::cout << "last_resort::foo" << std::endl; } } template<typename T> void bar(T) { using last_resort::foo; foo(T()); } namespace unrelated { struct type {}; } namespace base { struct type {}; void foo(type) { std::cout << "base::foo" << std::endl; } } namespace derived { struct type : base::type {}; } int main() { bar(unrelated::type()); // calls last_resort::foo bar(base::type()); // calls base::foo bar(derived::type()); // should call base::foo, but calls last_resort::foo instead return 0; } 
+6
source share
4 answers

last_resort::foo can be removed from the overload set with disable_if . The idea is to disable last_resort::foo(T) if foo(T) is otherwise well formed. This leads to the worst last_resort::foo(T) match for foo :

 namespace test { template<typename T> struct has_foo { ... }; } namespace last_resort { template<typename T> struct disable_if_has_foo : std::enable_if< !test::has_foo<T>::value > {}; template<typename T> typename disable_if_has_foo<T>::type foo(T) { std::cout << "last_resort::foo" << std::endl; } } 

Exit:

 $ g++ last_resort.cpp $ ./a.out last_resort::foo base::foo base::foo 

This answer describes how to build a solution to check for the existence of a function ( foo ) that returns void .

0
source

This will be about as bad as it gets:

 struct badParam { template <typename T> badParam(T t) { } }; namespace last_resort { void foo(badParam, int dummy = 0, ...) { std::cout << "last_resort::foo" << std::endl; } } 

You have a custom transform, a default option, and an unused ellipse.

[edit]

An insignificant option to save T I moved the user transformation to a dummy file parameter:

 struct badParam { badParam() { } operator int() { return 42; } }; namespace last_resort { template <typename T> void foo(T t, int dummy = badParam(), ...) { std::cout << "last_resort::foo" << std::endl; } } 
+2
source

You cannot do much. Both foo functions are in the overload set. But your last_resort alone is better suited simply because it doesn’t need a conversion other than base :: foo for the derived :: type (). Only in case when two candidates are “equally good”, judging by the parameters and possible transformations, not a template is preferable.

+1
source

You can provide a bar overload for the type derived::type after the declaration derived::type . It can be in namespace derived or not.

 void bar(derived::type) { foo(derived::type()); } 
0
source

Source: https://habr.com/ru/post/898401/


All Articles