我陷入了以下问题。我使用的是Xcode 7,但我的项目没有任何问题。尝试在Visual Studio Express 2015上对其进行编译后,我"Error C2668 ambiguous call to overloaded function"
在代码中得到了消息。我找不到与该问题有关的特定于Visual Studio的东西。
我做了一个应该在VS上使用的最小工作示例(Xcode上没有错误)。怪异的部分涉及该func2
部分。好像VS编译器无法自动推断出比限制更多的类型和/或参数。
更新 :
Sam Varshavchik提出了一种解决方法,其中包括将部分专业化与中间模板类一起使用。这是我要避免的解决方案。首先是因为它在上下文中不方便应用在我的代码中,其次是因为这个编译错误对我来说尚不清楚。Xcode7中不会显示此错误,即使在VS中func2也没有错误。尽管我同意WhiZTiM的解释,但事实是,在这种情况下,重载有时可以起作用,有时则不能。我真的很想知道为什么。
更新2:
根据bogdan的说法,这可能是GCC和MSVC中的错误。我将尝试举报。(我非常喜欢Visual Studio,这是我的第一周)
更新3:
错误报告于https://connect.microsoft.com/VisualStudio/feedback/details/3076577
template <class T>
class BX {
public :
BX() {}
~BX() {}
};
template <class T1, class T2>
class G {
public :
G() {}
~G() {}
};
template <template <class T> class T1, class T>
class DT {};
class B {
public :
//I want func to work
template <template <class T> class T1, class T, class M>
static void func(const M& m, const DT<T1, T>* dt, T1<T>& val) {}
template <template <class T> class T1, class T, class M>
static void func(const G<T1<T>, M>& g, const DT<T1, T>* dt, T1<T>& val) {}
//here is a small variation of func as a test
template <template <class T> class T1, class T, class M>
static void func2(const M& m, const DT<T1, T>* dt) {}
template <template <class T> class T1, class T, class M>
static void func2(const G<T1<T>, M>& g, const DT<T1, T>* dt) {}
};
main.cpp
int main() {
BX< int > bx;
G<BX< int >, int> g;
DT<BX, int>* dt;
B::func(g, dt, bx);//Error C2668 'B::func': ambiguous call to overloaded function
B::func2(g, dt);//no error
}
这看起来像MSVC和GCC中的错误。该调用应解决第二个过载(Clang和EDG正在这样做)。
对于call B::func(g, dt, bx)
,名称查找将找到两个func
模板。对模板参数进行推导和替换,以生成函数模板特化声明,这些声明随后可参与重载解析。两种模板的推论都成功,我们还剩下两个专长:
void B::func<BX, int, G<BX<int>, int>>(const G<BX<int>, int>&, const DT<BX, int>*, BX<int>&);
void B::func<BX, int, int> (const G<BX<int>, int>&, const DT<BX, int>*, BX<int>&);
这两个函数具有相同的参数声明子句,因此显然,重载解析无法基于调用参数的转换来区分它们。它必须求助于该过程的最后两个步骤。
首先,如果其中一个功能是模板专业化,而另一个功能不是模板专业化,则首选非模板功能。在这里不适用。
最后,它查看了合成两个专业化声明的模板。如果根据功能模板的部分排序,其中一个模板比另一个模板更专业,则首选相应的专业化。(这是过程中唯一恢复原始模板的位置。)
下面的描述不是很准确,并且跳过了很多细节,但是我尝试着重于与这种情况相关的部分。非常粗略:
首先,从两个模板的函数参数声明中删除引用和cv限定词,得到:
F1(M , const DT<T1, T>*, T1<T>)
F2(G<T2<U>, V>, const DT<T2, U>*, T2<U>)
(模板参数名称已更改以避免混淆)
然后,尝试进行推论,就好像是使用另一个模板的函数参数的形式作为参数调用一个模板,然后尝试使用另一种方法进行推导一样。在这种情况下,最后两对对应的参数具有相同的形式,因此推论在两种方法中都成功。对于第一对相应参数:
M
从形式的论点G<T2<U>, V>
作品; M
推导为G<T2<U>, V>
。T2
,U
并V
在G<T2<U>, V>
从形式的参数M
不工作(M
可以是任何东西)。换句话说,G<T2<U>, V>
是一种比“更具体”的形式M
;它不能代表所有M
可以代表的类型;这是更专业的人员试图在这种情况下进行形式化的直观含义。
因此,推导适用于从F2
到的所有对对应参数F1
,但反之则不行。这使得F2
更多的专业比F1
在偏序的条款。
这意味着在过载解析中,首选与第二个模板相对应的专业化。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句