C++ 使用具有相同参数的不同模板参数重载函数时出错
我有一个类,它获取两个模板参数,并使用一个参数重载一个函数,该参数要么是一个模板参数,要么是另一个模板参数,但两次都使用相同的模板参数:C++ 使用具有相同参数的不同模板参数重载函数时出错,c++,compiler-errors,overloading,template-templates,C++,Compiler Errors,Overloading,Template Templates,我有一个类,它获取两个模板参数,并使用一个参数重载一个函数,该参数要么是一个模板参数,要么是另一个模板参数,但两次都使用相同的模板参数: template<template<typename> class TemplArgA, template<typename> class TemplArgB> class CompileError { public: void func(TemplArgA<int> x) {} void func(Te
template<template<typename> class TemplArgA, template<typename> class TemplArgB>
class CompileError {
public:
void func(TemplArgA<int> x) {}
void func(TemplArgB<int> x) {}
};
模板
类编译器错误{
公众:
void func(TemplArgA x){}
void func(templargbx){}
};
我正在使用VC2010并获取
error C2535: 'void CompileError<TemplArgA,TemplArgB>::func(TemplArgA<int>)': member function already defined or declared
错误C2535:'void CompileError::func(TemplArgA)':成员函数已定义或声明
在编译上面的代码示例时(甚至在模板实例化时都没有,只是为了让代码中的上述行已经导致编译错误)
相比之下,这些标准很好:
template<class TemplArgA, class TemplArgB>
class Compiles {
public:
void func(TemplArgA x) {}
void func(TemplArgB x) {}
};
template<template<typename> class TemplArgA, template<typename> class TemplArgB>
class AlsoCompiles {
public:
void func(TemplArgA<int> x) {}
void func(TemplArgB<double> x) {}
};
模板
类编译{
公众:
void func(TemplArgA x){}
void func(templargbx){}
};
模板
类也可编译{
公众:
void func(TemplArgA x){}
void func(templargbx){}
};
知道我做错了什么吗
似乎可以用clang++编译,所以我想知道这是否是VC2010中的一个bug。。。如果是这样的话:你知道如何解决这个问题吗
别无选择,必须使用VC2010:(
如果是这样的话:你知道如何解决这个问题吗
所以,你可以试试
template<template<typename> class TemplArgA, template<typename> class TemplArgB>
class CompileError {
public:
void func(TemplArgA<int> x) {}
void func(TemplArgB<int> x,void* workaround = 0) {}
模板
类编译器错误{
公众:
void func(templaga x){}
void func(TemplArgB x,void*变通方法=0){}
当然,这并不完全等同于您的原始代码(因为在TemplArgA==TemplArgB的情况下,只有在函数实例化时才会出现错误;我不知道这是否与您相关)
但是在真正的代码中,我不仅仅有TemplArgA和TemplArgB,还有4个模板参数(比如TemplArgA到TemplArgD)——我不认为我可以应用解决方法
您只需说服编译器这些重载不是等效的:
template<int> struct workaround_t{};
void func(TemplArgA<int> x, workaround_t<0>* workaround = 0) {}
void func(TemplArgB<int> x, workaround_t<1>* workaround = 0) {}
void func(TemplArgC<int> x, workaround_t<2>* workaround = 0) {}
//...
模板结构解决方案{};
void func(TemplArgA x,变通方法_t*变通方法=0){}
void func(TemplArgB x,变通方法_t*变通方法=0){}
void func(TemplArgC x,变通方法_t*变通方法=0){}
//...
我想问题是编译器看到并错误地发现可能的IStantation winTemplArgA==templarargb
(当两个func()
冲突时),所以我想(如果可以使用C++11)另一个解决方法是SFINAE启用(或不启用)第二个func()
仅idTemplArgA!=TemplArgB
我是说
template <template <typename> class C1, template <typename> class C2>
struct bar
{
void func (C1<int> x)
{ }
template <template <typename> class D2 = C2>
typename std::enable_if< std::is_same<C2<int>, D2<int>>{}
&& ( ! std::is_same<C1<int>, D2<int>>{})>::type
func (D2<int> x)
{ }
};
第四个呢
template <template <typename> class D4 = C4>
typename std::enable_if< std::is_same<C4<int>, D4<int>>{}
&& ( ! std::is_same<C1<int>, D4<int>>{})
&& ( ! std::is_same<C2<int>, D4<int>>{})
&& ( ! std::is_same<C3<int>, D4<int>>{})>::type
func (D4<int> x)
{ }
模板
typename std::enable_if::类型
func(D4 x)
{ }
)但我希望它能起作用
下面是一个完整的工作示例(但使用g++和clang++;我不使用VC2010)
#包括
#包括
#包括
模板结构foo1{};
模板结构foo2{};
模板结构foo3{};
模板结构foo4{};
模板
结构条
{
无效函数(C1 x)
{ }
模板
typename std::enable_if::类型
func(d2x)
{ }
模板
typename std::enable_if::类型
func(D3 x)
{ }
模板
typename std::enable_if::类型
func(D4 x)
{ }
};
int main()
{
棒b1234;
棒b1111;
棒b1112;
棒b1121;
棒b1211;
棒b2111;
}
找到了适合我的解决方案:
enum eSelector { S_A, S_B };
template<template<typename,eSelector> class TemplArg>
class Workaround {
public:
void func(TemplArg<int, S_A> x) {}
void func(TemplArg<int, S_B> x) {}
};
枚举选择器{S_A,S_B};
模板
类解决方法{
公众:
void func(TemplArg x){}
void func(TemplArg x){}
};
通过这种方式,VC2010编译时没有C2535。这使得作为模板参数提供的类更加复杂。我正式地进行了分类
template<typename T> class MyA { ... };
template<typename T> class MyB { ... };
模板类MyA{…};
模板类MyB{…};
我用作模板参数,现在使用部分模板专门化,如
template<typename T, eSelector S> class MyAB;
template<typename T> class MyAB<T, S_A> { ... };
template<typename T> class MyAB<T, S_B> { ... };
template<typename T> class MyA : public MyAB<T, S_A> { /* `forward' constructor implementations */ };
template<typename T> class MyB : public MyAB<T, S_B> { /* `forward' constructor implementations */ };
模板类MyAB;
模板类MyAB{…};
模板类MyAB{…};
模板类MyA:公共MyAB{/*`forward'构造函数实现*/};
模板类MyB:公共MyAB{/*`forward'构造函数实现*/};
无论如何,使用这种方法,事情看起来要复杂得多,所以我对此并不满意。我将尝试使用Massimiliano编辑的帖子中的建议,认为这会使代码看起来不那么可怕;但为了完整性,我还是想提供这种方法;)
我仍然想知道你是否遗漏了一些重要的东西,或者它是否是VC2010 bug…为什么不使用2017?没有选择,必须使用VC2010:(VC阻塞了模板定义本身,或者是实例化导致了问题?模板定义本身。我认为TemplArgA==Templargbcase在这两种情况下都不会给出错误,直到函数实例化,不是吗?无论如何,这与我无关。@thilo,不,在您的原始代码中(我的意思是,对于一致的编译器)一旦类模板被实例化,您就会得到一个错误(但是,我不确定这种诊断在多大程度上是标准的,我应该检查一下…)使用建议的解决方法编译,这是一个好主意。但是在实际代码中,我不只有TemplArgA和TemplArgB,而是4个模板参数(说TemplArgA到TemplArgD)--我认为我无法应用解决方法:(@thilo,作为旁注,根据,我确认需要在类模板实例化时对原始代码的ArgA==ArgB情况进行诊断。“我仍然怀疑…”这肯定是一个vc错误,请参阅
template<typename T> class MyA { ... };
template<typename T> class MyB { ... };
template<typename T, eSelector S> class MyAB;
template<typename T> class MyAB<T, S_A> { ... };
template<typename T> class MyAB<T, S_B> { ... };
template<typename T> class MyA : public MyAB<T, S_A> { /* `forward' constructor implementations */ };
template<typename T> class MyB : public MyAB<T, S_B> { /* `forward' constructor implementations */ };