I want to change the instantiate order of the overload templates. My code are as follow:
#include <iostream>
#include <vector>
using namespace std;
template<typename T>
struct Base
{
};
template<typename T>
struct Derived:Base<T>
{
};
//template 1
template<typename T1>
void f(Base<T1>& a){
cout<<"in 1\n";
}
//template 2
template<typename T2>
void f(T2 b){
cout<<"in 2\n";
}
int main(){
Derived<int> v1;
f(v1);
}
The compiler will chose template 2 as default, but I want it to chose template 1.
With custom traits
template <typename T> std::true_type derive_from_base_impl(const Base<T>*);
std::false_type derive_from_base_impl(...);
template <typename T>
using derive_from_base = decltype(derive_from_base_impl(std::declval<T*>()));
static_assert(!derive_from_base<int>::value, "");
static_assert(derive_from_base<Derived<int>>::value, "");
And SFINAE, you may do
template<typename T>
void f(Base<T>& a) { std::cout << "in 1\n"; }
template<typename T>
std::enable_if_t<!derive_from_base<T>::value>
f(T b) { std::cout << "in 2\n"; }
Demo
The right term for this is overload resolution preferences, and second overload is chosen because it is a better match. It appeared to be more challenging than I expected to put together a code which would make sure proper overload was selected. Here it is:
#include <type_traits>
#include <iostream>
template<typename T>
struct Base { };
template<typename T>
struct Derived:Base<T> { };
template <class T>
struct template_argument { using type = void*; };
template <template <class > class T, class ARG>
struct template_argument<T<ARG> > {
using type = ARG;
};
template <class T>
using template_argument_t = typename template_argument<T>::type;
template<typename T1>
void f(Base<T1>& ){
std::cout << "Base-expecting f called\n";
}
template<class T>
void f(T, std::enable_if_t<!std::is_base_of<Base<template_argument_t<T> >, T>::value>* = nullptr ) {
std::cout << "Generic f was called.\n";
}
template <class T>
struct Z { };
int main(){
Derived<int> v1;
f(v1);
f(int() );
f(Z<int>() );
}
Output:
Base-expecting f called
Generic f was called.
Generic f was called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With