Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;模板和对重载函数的不明确调用_C++_Visual Studio_Templates_Overloading - Fatal编程技术网

C++ c++;模板和对重载函数的不明确调用

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提出了一个解决方案,其中包括

我遇到了以下问题。我使用的是Xcode 7,对我的项目没有任何问题。在尝试在Visual Studio Express 2015上编译它之后,我在代码中得到消息“Error C2668对重载函数的不明确调用”。我找不到与此问题相关的任何特定于visual studio的内容

我制作了一个应该在VS上使用的最小工作示例(Xcode上没有错误)。奇怪的部分包括
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>)