明确选择应使用哪个模板重载

时间:2017-04-02 09:34:48

标签: c++ templates overloading

我们可以选择在这种情况下应该使用哪个函数模板重载吗?

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

int main() {
    /* explicitly choose overload */ fun(1, X());
}

错误:

error: call of overloaded 'fun(int, X)' is ambiguous
     /* explicitly choose overload */ fun(1, X());
                                                ^
    candidate: void fun(T, A) [with T = int]
 void fun(T, A) { }
      ^~~
    candidate: void fun(T, B) [with T = int]
 void fun(T, B) { }
      ^~~

对于正常功能,它看起来像这样:

void fun(A){}
void fun(B){}

int main() {
    ((void(*)(A))(fun))(X());
}

有可能吗?

3 个答案:

答案 0 :(得分:3)

改进您的示例,您可以尝试使用

 ((void(*)(int, A))(fun))(1, X());

答案 1 :(得分:2)

如果您选择不显式指定第一个参数类型但仍希望指定第二个参数类型,则可以使用专用于转换目的的lambda(c ++ 14解决方案):

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

int main() {
    [](auto v, auto x){ static_cast<void(*)(decltype(v), A)>(fun)(v, x); }(1, X());
}

[live demo]

答案 2 :(得分:1)

这个问题的低技术解决方案是添加一个额外的间接级别。添加funA之类的函数,其唯一目的是为fun的第一个版本提供明确的名称:

struct X { };

struct A { A(X){} };
struct B { B(X){} };

template<class T>
void fun(T, A) { }

template<class T>
void fun(T, B) { }

template <class T>
void funA(T t, A a) { fun(t, a); }

int main() {
    /* explicitly choose overload */ funA(1, X());
}

但是,我想知道为什么你不能只将参数改为A(X())。你无论如何都必须改变主叫代码,那么问题是什么?