I have a class
template <typename T, typename W>
class A {
void foo(W);
void foo(T);
void foo(int);
}
When T=int
, W=int
, or W=T
, this class fails to compile. How can I get the methods to take priority over each other?
I want the priority W > T > int
. So if W=T
, foo(T)
is ignored and foo(W)
is called. If T=int
, foo(int)
is ignored and foo(T)
is called.
The compiler is VS2012, but I have Linux too, and will consider GCC/Clang solutions as well. Anything that compiles on any mainstream compiler goes, but only if you say what compilers it works on.
I would tag dispatch. Override dispatching is easy to understand and scales.
We start with a perfect forwarder:
template<class U> void foo(U&&u){
foo( std::forward<U>(u), std::is_convertible<U, W>{}, std::is_convertible<U,T>{} );
}
it creates tag types, in this case true or false types, to dispatch on.
This one:
void foo( W, std::true_type, ... );
catches everything that can convert to W.
Next, we block this one:
void foo( T, std::false_type, std::true_type );
from considerimg cases where the first argument can convert to W
.
Finally, this one:
void foo( int, std::false_type, std::false_type );
can only be considered if the first parameter cannot convert to either.
Fancier tag types, or doing the dispatching one at a time, are both possible.
Sorry for typos.
I use a single C++11 feature -- {}
to construct an object -- above. If your compiler lacks support for that C++11 feature, simply upgrade your compiler, it is 2014, get with it. Failing that, replace {}
with ()
.
Use std::enable_if
:
#include <type_traits>
template <typename T, typename W>
struct A {
void foo(W) {}
template<typename XT=T> typename std::enable_if<std::is_same<XT,T>::value
&& !std::is_same<T, W>::value, void>::type foo(T) {}
template<typename XT=int> typename std::enable_if<std::is_same<XT,int>::value
&& !std::is_same<int, T>::value
&& !std::is_same<int, W>::value, void>::type foo(int) {}
};
Added for testing:
template struct A<short,char>;
template struct A<char,char>;
template struct A<char,int>;
template struct A<int,char>;
template struct A<int, int>;
struct S {};
int main() {
A<S, int>{}.foo(S{});
}
For the relevant part of your template, you could use speclializations:
template <typename U, typename W>
struct Foo
{
void f(U);
void f(W);
};
template <typename T>
struct Foo<T, T>
{
void f(T);
};
For the rest of your class or class template, you can inherit from Foo<A, B>
so you can keep the common code out of the part that needs to be specialized:
template <typename A, typename B>
struct TheClass : Foo<A, B>
{
// common code
};
Try template specializations:
template <typename T, typename W>
class A {
void foo(W);
void foo(T);
void foo(int);
};
template <typename T>
class A<T, T> {
void foo(T);
void foo(int);
};
template <>
class A<int, int> {
void foo(int);
};
Here is a solution without specializations of A, but with two helper structures in a few forms.
#include <iostream>
template<typename T, typename W>
struct T_type { typedef T type; };
template<typename W>
struct T_type<W, W> { typedef void* type; /*dummy type*/};
template<typename T, typename W>
struct int_type { typedef int type; };
template<typename W>
struct int_type<int, W> { typedef void** type; /*dummy type*/};
template<typename T>
struct int_type<T, int> { typedef void** type; /*dummy type*/};
template<>
struct int_type<int, int> { typedef void** type; /*dummy type*/};
template<typename T, typename W>
class A {
public:
void foo(W w) {
std::cout << "foo(W)" << std::endl;
}
void foo(typename T_type<T, W>::type t) {
std::cout << "foo(T)" << std::endl;
}
void foo(typename int_type<T, W>::type i) {
std::cout << "foo(int)" << std::endl;
}
};
int main() {
std::cout << "A<float, char>" << std::endl;
A<float, char> a;
a.foo(1.0f);
a.foo('1');
a.foo(1);
std::cout << "A<float, float>" << std::endl;
A<float, float> b;
b.foo(1.0f);
b.foo(1);
std::cout << "A<int, int>" << std::endl;
A<int, int> c;
c.foo(1);
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.