C++ 同一个类中具有不同类型名的同一模板的多个专门化

C++ 同一个类中具有不同类型名的同一模板的多个专门化,c++,templates,C++,Templates,我正在实现一个观察者模式作为模板,并希望一个类具有不同的侦听器类型。问题在于,似乎不可能在一个类中多次使用同一个模板来处理不同的类型。据我所知,这应该是可能的,因为方法名无论如何都会有不同的类型,所以它们应该被压缩成不同的名称。然而,我得到的错误不是在linktime,而是在compiletime,所以我想知道我做错了什么,或者这是否完全不可能 为了演示这个问题,我编写了一个SSCE: #include <iostream> #include <string> temp

我正在实现一个观察者模式作为模板,并希望一个类具有不同的侦听器类型。问题在于,似乎不可能在一个类中多次使用同一个模板来处理不同的类型。据我所知,这应该是可能的,因为方法名无论如何都会有不同的类型,所以它们应该被压缩成不同的名称。然而,我得到的错误不是在linktime,而是在compiletime,所以我想知道我做错了什么,或者这是否完全不可能

为了演示这个问题,我编写了一个SSCE:

#include <iostream>
#include <string>

template<typename T>
class Comparator
{
public:
    Comparator(void) { mCounter = 0; };
    virtual ~Comparator(void) {};

    bool equals(T oFirst, T oSecond)
    {
        mCounter++;
        if(oFirst != oSecond)
            return false;

        return true;
    }

    int getCounter(void)
    {
        return mCounter;
    }

private:
    int mCounter;
};

class TestClass :
    public Comparator<int>,
    public Comparator<void *>
{
public:
    TestClass(void) {};
    virtual ~TestClass(void) {};
};

int main(int argc, char *argv[])
{
    TestClass t1;
    TestClass *t2 = &t1;
    TestClass *t3 = new TestClass();
    int v1 = 1;
    int v2 = 2;
    bool b = t1.equals(v1, v2);
    std::cout << b << std::endl;
    std::cout << t1.equals(&t1, &t2) << std::endl;
    std::cout << t1.getCounter() << std::endl;

    delete t3;

    return 0;
}
#包括
#包括
模板
类比较器
{
公众:
比较器(void){mCounter=0;};
虚拟比较器(void){};
bool等于(第一个的T,T秒)
{
mCounter++;
如果(oFirst!=秒)
返回false;
返回true;
}
int getCounter(无效)
{
返回mCounter;
}
私人:
int mCounter;
};
类TestClass:
公共比较机构,
公共比较器
{
公众:
TestClass(void){};
虚~TestClass(void){};
};
int main(int argc,char*argv[])
{
测试类t1;
TestClass*t2=&t1;
TestClass*t3=新的TestClass();
int v1=1;
int v2=2;
布尔b=t1,等于(v1,v2);

std::cout您希望基类中的
equals
参与重载解析,就好像它们都是在派生类中定义的一样,但不幸的是,它不能以这种方式工作(我不确定为什么不能)

您可以显式调用所需的
equals
版本:

t1.Comparator<int>::equals(v1, v2);
t1.比较器::等于(v1,v2);
或者,您可以将其添加到派生类(公共部分):

使用Comparator::equals;
使用Comparator::equals;
这应该允许基类中的2个equals函数执行标准重载解析。您也可以通过在派生类中编写2个equals函数并让每个函数调用相应的基类
equals
来实现相同的目标


需要注意的是:
Comparator
Comparator
是完全独立的类。它们彼此互不了解。如果它们不是模板,但名称也不同,则表现相同。

此外,我想你的意思是:
t1.equals(t1,t2)
就是这样:
t1.equals(&t1,t2)
(或者可能
t1.equals(t2,t3)
)。
equals()
不使用对象中的任何信息,因此也可以是静态的。
。此外,我看不出类应该是多态的任何原因。@dlf,是的,你是对的。但由于这只是一个小例子,它说明了问题。代码无法工作是另一个问题,但与问题无关。我还是解决了它。@iavr,这是正确的除此之外,我不是在谈论OO建模,我是在谈论SSCE演示的一个特定问题。@Devolus当然,如果我集中精力解决这个问题,我可能会第一个回答:-)还有一点信息:
Comparator
是一个模板这一事实并不重要。如果您编写了两个名为ComparatorInt和ComparatorVp的非模板基类,您会得到完全相同的行为。但是,如果这两个
equals()
实际上都是在
TestClass
中实现的,而不是在基类中实现的(或在同一个基类中实现),模糊性消失。看起来,来自两个不同基类的可接受名称匹配被认为同样好,即使其中一个比另一个更适合参数。“我不确定为什么不”:如果是另一种方式(默认情况下使用基成员),没有办法禁用它们,并且定义了一个新的
equals
,它没有重载任何内容。但我个人更喜欢默认使用它们(这肯定更常见),如果需要,该语言还有另一种方法禁用它们(如
=delete
)。感谢您的检查。这实际上是一个
多重继承问题,而不是一个真正的模板问题。尽管如此,我还是希望编译器能够确定正确的调用,但至少我现在理解了错误消息。@Devolus不仅仅是一个多重继承问题。如果其中一个
equals
在基中,另一个在派生中。@Dave似乎恰到好处(尽管它没有提供标准引号来支持其断言)。
t1.Comparator<int>::equals(v1, v2);
using Comparator<int>::equals;
using Comparator<void*>::equals;