C++ c++;模板和对重载函数的不明确调用
我遇到了以下问题。我使用的是Xcode 7,对我的项目没有任何问题。在尝试在Visual Studio Express 2015上编译它之后,我在代码中得到消息“Error C2668对重载函数的不明确调用”。我找不到与此问题相关的任何特定于visual studio的内容 我制作了一个应该在VS上使用的最小工作示例(Xcode上没有错误)。奇怪的部分包括C++ c++;模板和对重载函数的不明确调用,c++,visual-studio,templates,overloading,C++,Visual Studio,Templates,Overloading,我遇到了以下问题。我使用的是Xcode 7,对我的项目没有任何问题。在尝试在Visual Studio Express 2015上编译它之后,我在代码中得到消息“Error C2668对重载函数的不明确调用”。我找不到与此问题相关的任何特定于visual studio的内容 我制作了一个应该在VS上使用的最小工作示例(Xcode上没有错误)。奇怪的部分包括func2部分。这就好像VS编译器无法自动推断出比限制更多的类型和/或参数 更新: Sam Varshavchik提出了一个解决方案,其中包括
func2
部分。这就好像VS编译器无法自动推断出比限制更多的类型和/或参数
更新:
Sam Varshavchik提出了一个解决方案,其中包括对中间模板类使用部分专门化。这是我想要避免的解决方案。首先是因为它在我的代码中应用的上下文中不方便,其次是因为我不清楚这个编译错误。这个错误在Xcode7中没有出现,func2甚至在VS中也没有错误。尽管我同意对WhiZTiM的解释,但事实是,在这种情况下重载有时可以工作,有时不能。我很想知道为什么
更新2:
根据bogdan的说法,这可能是GCC和MSVC中的一个bug。我要去报告一下。(我非常喜欢visual studio的第一周)
更新3:
错误报告于
职能.h:
模板
BX类{
公众:
BX(){}
~BX(){}
};
模板
G类{
公众:
G(){}
~G(){}
};
模板
类DT{};
B类{
公众:
//我想让func工作
模板
静态void func(常数M&M,常数DT*DT,T1&val){}
模板
静态void func(常数G&G,常数DT*DT,T1&val){}
//这里是func的一个小变化作为测试
模板
静态void func2(常数M&M,常数DT*DT){}
模板
静态void func2(常数G&G,常数DT*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
}
intmain(){
BXBX;
G、 int>G;
DT*DT;
B::func(g,dt,bx);//错误C2668'B::func':对重载函数的调用不明确
B::func2(g,dt);//无错误
}
您打了这个电话:
B::func(g, dt, bx);
其中:
类型为g
g,int>
属于dt
dt*
属于bx
bx
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) {}
//^^^^^^^^^^^^^^^^^^
模板
静态void func(常数M&M,常数DT*DT,T1&val){}
//^^^^^^^^^^
模板
静态void func(常数G&G,常数DT*DT,T1&val){}
//^^^^^^^^^^^^^^^^^^
过载解决期间;并且只考虑函数声明中的第一个参数(因为这些参数可能会使函数声明有所不同):
- 第一个函数中的
重载被推断为M
李>G,int>
- 第二个函数重载具有应匹配的模板类型。
可以从T
作为bx
int
一种模板类型,由T1
推断为bx
bx
将匹配任何内容M
- 一天结束时,第一个参数被推导为
,与第一个函数的参数相同G,int>
要在传递
G
类型时优先使用第二个重载函数,需要使用部分专门化。(因为它们的排名高于主模板)。请看
一种可能的方法。所示代码的明显意图是部分函数专门化 这…是行不通的 那么,该做什么,该做什么。。。那么,将部分函数专门化转换为普通模板类专门化如何 我的解决方案在第一个函数参数类型上专门使用一个模板,以消除静态类的歧义,并将其转发给两个最终类方法之一
一个好的C++编译器应该能够优化额外的函数调用层:
template <class T>
class BX {
public :
BX() {}
~BX() {}
};
template <class Tdata, class Tmetric>
class G {
public :
G() {}
~G() {}
};
template <template <class T> class T1, class T>
class DT {};
template<class M> class B_func;
class B {
public :
template <template <class T> class T1, class T, class M>
static void func(const M& m, const DT<T1, T>* dt, T1<T>& val)
{
B_func<M>::func(m, dt, val);
}
template <template <class T> class T1, class T, class M>
static void func_a(const M& m, const DT<T1, T>* dt, T1<T>& val) {}
template <template <class T> class T1, class T, class M>
static void func_b(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) {}
};
template <class M>
class B_func {
public:
template<class two, class three>
static void func(const M& m, const two* dt, three& val)
{
B::func_a(m, dt, val);
}
};
template <template <class T> class T1, class T, class M>
class B_func<G<T1<T>, M>> {
public:
template<class two, class three>
static void func(const G<T1<T>, M>& m, const two* dt, three& val)
{
B::func_b(m, dt, val);
}
};
int main() {
BX< int > bx;
G<BX< int >, int> g;
DT<BX, int>* dt;
B::func(g, dt, bx);
B::func2(g, dt);
return 0;
}
模板
BX类{
公众:
BX(){}
~BX(){}
};
模板
G类{
公众:
G(){}
~G(){}
};
模板
类DT{};
模板类B_func;
B类{
公众:
模板
静态无效函数(常数M&M、常数DT*DT、T1&val)
{
B_func::func(m,dt,val);
}
模板
静态无效函数a(常数M&M,常数DT*DT,T1&val){}
模板
静态无效函数b(常数G&G,常数DT*DT,T1&val){}
//这里是func的一个小变化作为测试
模板
静态void func2(常数M&M,常数DT*DT){}
模板
静态void func2(常数G&G,常数DT*DT){}
};
模板
B_func类{
公众:
模板
静态无效函数(常数M&M,常数2*dt,常数3&val)
{
B::func_a(m,dt,val);
}
};
模板
B_func类{
公众:
模板
静态无效函数(常数G&m,常数2*dt,常数3&val)
{
B::func_B(m,dt,val);
}
};
int main(){
BXBX;
G、 int>G;
DT*DT;
B::func(g,dt,bx);
B::func2(g,dt);
返回0;
}
这看起来像MSVC和GCC中的一个bug。调用应解析为第二个重载(Clang和EDG正在这样做)
对于调用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>&);
void B::func(常数G&,常数DT*,BX&);
void B::func(常数G&,常数DT*,BX&);
这两个函数具有相同的参数decl
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>&);
F1(M , const DT<T1, T>*, T1<T>)
F2(G<T2<U>, V>, const DT<T2, U>*, T2<U>)