我有一个班级
template <typename T, typename W>
class A {
void foo(W);
void foo(T);
void foo(int);
}
当T=int
,W=int
或W=T
时,此类无法编译。如何让方法优先于彼此?
我想要优先级W > T > int
。因此,如果忽略W=T
,foo(T)
,则会调用foo(W)
。如果T=int
,则忽略foo(int)
并调用foo(T)
。
编译器是VS2012,但我也有Linux,并且也会考虑GCC / Clang解决方案。任何编译在任何主流编译器上的东西都会出现,但前提是你说它的工作原理是什么编译器。
答案 0 :(得分:3)
我会标记发送。覆盖调度很容易理解和扩展。
我们从一个完美的货运代理开始:
template<class U> void foo(U&&u){
foo( std::forward<U>(u), std::is_convertible<U, W>{}, std::is_convertible<U,T>{} );
}
它会创建标记类型,在本例中为true或false类型,以便分发。
这一个:
void foo( W, std::true_type, ... );
捕获可转换为W的所有内容。
接下来,我们阻止这一个:
void foo( T, std::false_type, std::true_type );
来自于考虑第一个参数可以转换为W
的情况。
最后,这一个:
void foo( int, std::false_type, std::false_type );
只有在第一个参数无法转换为任何参数时才能考虑。
Fancier标签类型,或者一次调度一个,都是可能的。
抱歉打字错误。
我使用单个C ++ 11特性 - {}
来构造一个对象 - 上面。如果您的编译器缺乏对该C ++ 11功能的支持,只需升级您的编译器,它就是2014年,随便使用它。如果做不到,请将{}
替换为()
。
答案 1 :(得分:2)
使用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) {}
};
已添加用于测试:
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{});
}
答案 2 :(得分:1)
对于模板的相关部分,您可以使用speclializations:
template <typename U, typename W>
struct Foo
{
void f(U);
void f(W);
};
template <typename T>
struct Foo<T, T>
{
void f(T);
};
对于您的类或类模板的其余部分,您可以继承Foo<A, B>
,这样您就可以将公共代码保留在需要专门化的部分之外:
template <typename A, typename B>
struct TheClass : Foo<A, B>
{
// common code
};
答案 3 :(得分:0)
尝试模板专精:
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);
};
答案 4 :(得分:0)
这是一个没有A特化的解决方案,但有几种形式的两个辅助结构。
#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;
}