Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++ gcc4模板错误或更可能的id10t错误_C++_Templates_Gcc_Compiler Construction_Gcc4 - Fatal编程技术网

C++ gcc4模板错误或更可能的id10t错误

C++ gcc4模板错误或更可能的id10t错误,c++,templates,gcc,compiler-construction,gcc4,C++,Templates,Gcc,Compiler Construction,Gcc4,下面的代码在VisualStudio下编译得很好,但GCC4.6.2或4.7都无法处理。它似乎是有效的,但gcc似乎无法解决常量和非常量参数之间的差异。这可能是一个编译器错误吗 struct CReadType{}; struct CWriteType{}; template<typename ReadWriteType, typename T> struct AddPkgrConstByType {}; template<typename T> struct A

下面的代码在VisualStudio下编译得很好,但GCC4.6.2或4.7都无法处理。它似乎是有效的,但gcc似乎无法解决常量和非常量参数之间的差异。这可能是一个编译器错误吗

struct CReadType{};
struct CWriteType{};

template<typename ReadWriteType, typename T> 
struct AddPkgrConstByType {}; 
template<typename T> 
struct AddPkgrConstByType<CReadType, T> {
   typedef T type;
};    
template<typename T>
struct AddPkgrConstByType<CReadType, const T> {
    typedef T type;
};
template<typename T>
struct AddPkgrConstByType<CWriteType, T> {
    typedef T const type;
};

template<typename Packager, typename T>
struct AddPkgrConst : public AddPkgrConstByType<typename Packager::CReadWriteType, T> {
};

template<typename Packager, typename T>
inline bool Package( Packager* ppkgr, T* pt ) 
{
    return true;
}

template<typename Packager>
inline bool Package( Packager* ppkgr, typename AddPkgrConst<Packager,bool>::type* pb) 
{
    return false;
}

struct ReadPackager {
    typedef CReadType CReadWriteType;
};
struct WritePackager {
    typedef CWriteType CReadWriteType;
};

int main(int argc, char* argv[])
{
    ReadPackager rp;
    WritePackager wp;
    bool b = true;
    const bool cb = false;
    Package( &rp, &b );
}
struct-CReadType{};
结构CWriteType{};
模板
结构AddPkgrConstByType{};
模板
结构AddPkgrConstByType{
T型;
};    
模板
结构AddPkgrConstByType{
T型;
};
模板
结构AddPkgrConstByType{
typedef T const type;
};
模板
结构AddPkgrConst:public AddPkgrConstByType{
};
模板
内联bool包装(包装商*ppkgr,T*pt)
{
返回true;
}
模板
内联布尔包(包装商*ppkgr,类型名AddPkgrConst::类型*pb)
{
返回false;
}
结构读取器{
typedef CReadType CReadWriteType;
};
结构写包器{
typedef CWriteType CReadWriteType;
};
int main(int argc,char*argv[])
{
阅读器包装机;
WritePackager wp;
布尔b=真;
const bool cb=假;
包装(&rp,&b);
}
编译器调用:

g++ -fPIC -O -std=c++0x -Wno-deprecated -D_REENTRANT 
g++-D__STDC_LIMIT_MACROS -c test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:58:22: error: call of overloaded ‘Package(ReadPackager*, bool*)’ is ambiguous
test.cpp:58:22: note: candidates are:
test.cpp:31:6: note: bool Package(Packager*, T*) [with Packager = ReadPackager, T = bool]
test.cpp:38:6: note: bool Package(Packager*, typename AddPkgrConst<Packager, bool>::type*) [with Packager = ReadPackager, typename AddPkgrConst<Packager, bool>::type = bool]
g++-fPIC-O-std=c++0x-Wno已弃用-D_可重入
g++-D_ustdc_LIMIT_宏-c test.cpp
test.cpp:在函数“int main(int,char**)”中:
test.cpp:58:22:错误:重载的“Package(ReadPackager*,bool*)”调用不明确
考试。cpp:58:22:注:考生为:
test.cpp:31:6:注:bool包(Packager*,T*)[带Packager=ReadPackager,T=bool]
test.cpp:38:6:注:bool包(Packager*,typename AddPkgrConst::type*)[带Packager=ReadPackager,typename AddPkgrConst::type=bool]

我不知道Visual Studio有什么问题,但是
gcc
所说的似乎是正确的:


实例化
AddPkgrConstByType
是因为
Packager::CReadWriteType
解析为
CReadType
。因此,
AddPkgrConst::type
将根据第一个实现(不是专门化)解析为
bool
。这意味着你有两个独立的函数专长,它们的参数列表相同,C++不允许你。

因为函数模板不能被专门化,这里有两个函数模板重载。这两个重载都能够接受
bool*
作为它们的第二个参数,因此g++可以正确地检测到它们是不明确的

然而,类可以部分地专门化,这样只会选择一个版本,并且您可以使用包装器魔术来实现您想要的目标。我只是粘贴我添加的代码

template <typename Packager, typename T>
struct Wrapper
{
    static bool Package()
    {
        return true;
    }
};

template <typename Packager>
struct Wrapper<Packager, typename AddPkgrConst<Packager,bool>::type>
{
    static bool Package()
    {
        return false;
    }
};

template <typename Packager, typename T>
Wrapper<Packager, T> make_wrapper(Packager* /*p*/, T* /*t*/)
{
    return Wrapper<Packager, T>();
}

int main()
{
    ReadPackager rp;
    bool b = true;
    std::cout << make_wrapper(&rp, &b).Package() << std::endl;  // Prints out 0.
}
模板
结构包装器
{
静态bool包()
{
返回true;
}
};
模板
结构包装器
{
静态bool包()
{
返回false;
}
};
模板
包装机制造包装机(包装机*/*p*/,T*/*T*/)
{
返回包装器();
}
int main()
{
阅读器包装机;
布尔b=真;

std::cout这在我看来像是编译器错误。这里涉及的问题是模板函数的重载解析和偏序。由于两个模板函数都可以匹配参数列表
(ReadPackager*,bool)
,因此应该使用模板函数的偏序来选择更专业的模板函数

简单地说,如果一个模板函数的参数始终可以用作另一个模板函数的参数,那么该模板函数至少与另一个模板函数一样专用

很明显,任何两个指针参数都与第一个Package()函数匹配,但例如Package(ReadPackager*,const int*)不能与第二个匹配。这似乎意味着第二个Package函数更专业,应该解决任何歧义

但是,由于编译器之间存在分歧,因此可能会涉及一些被简化解释忽略的微妙之处。因此,我将遵循从标准中确定函数模板偏序的过程,以识别正确的行为

首先,将函数标记为P1和P2以便于参考

P1:

模板
bool包装(包装商*ppkgr,T*pt);
P2:

模板
bool包装(包装商*ppkgr,类型名称AddPkgrConst::类型*pb);
该标准规定,对于每个模板函数(T1),我们必须为其每个模板参数创建泛型唯一类型,使用这些类型确定函数调用参数类型,然后使用这些类型推断其他模板(T2)中的类型。如果成功,则第一个模板(T1)至少与第二个模板(T2)一样专用。 第一个P2->P1

  • 为P2的模板参数
    Packager
    合成唯一类型
    U
  • P1
    的参数列表执行类型推断。
    Packager
    被推断为
    U
    T
    被推断为
    AddPkgrConst::type
  • 此操作成功,P1被判断为不比P2更专业化

    现在P1->P2:

  • 合成P1的模板参数
    Packager
    T
    的唯一类型
    U1
    U2
    ,以获得参数列表(U1*,U2*)
  • 根据
    P2
    的参数列表执行类型推断。
    包装商
    推断为U1
  • 第二个参数不执行推断,因为它是依赖类型,被视为非推断上下文
  • 因此,第二个参数是
    AddPkgrConst::type
    ,其计算结果为
    bool
    。这与第二个参数
    U2
    不匹配
  • < P >这个过程如果我们进入第4步失败了。然而,我怀疑,拒绝这个代码的编译器不执行步骤4,因此认为P2没有比P1更专业化,仅仅因为类型推导成功。这似乎是违反直觉的,因为P1清楚地接受了P2所做的任何输入,反之亦然。dard有些复杂,所以不清楚最后的比较
    template<typename Packager, typename T>
    bool Package( Packager* ppkgr, T* pt );
    
    template<typename Packager>
    bool Package( Packager* ppkgr, typename AddPkgrConst<Packager,bool>::type* pb);