具有编译时已知参数的纯虚拟成员函数?

Pure Virtual member function with compile-time known parameter?

我正在通过尝试为 STL 容器实现一个类型擦除模式来练习类型擦除模式,但我坚持使用这些容器的纯虚拟成员函数。我不知道如何实现作为接口的类型擦除模式的 "concept",保存被擦除类型共享的纯虚拟成员函数。像 Push 这样的函数需要一个编译时已知的参数。据我了解,虚函数不能使用auto或模板化,那么我该如何编写接口?

我试过用关键字'typename'告诉编译器稍后会给出类型,但是编译不通过

这是我目前对 'concept' 界面的了解:

class Concept{
public:
    virtual void push(typename T val) = 0;
    virtual typename T pop() = 0;
};

目前收到的错误是这样的:

error: expected nested-name-specifier before ‘T’ virtual void push(typename T val) = 0;
                              ^
error: expected ‘,’ or ‘...’ before ‘val’ virtual void push(typename T val) = 0;
                                ^~~
error: expected nested-name-specifier before ‘T’ virtual typename T pop() = 0;

如果有人能就此给我一些建议,我将不胜感激。预先感谢大家的热心帮助和宝贵时间。

typename 关键字只能是模板声明的一部分。

template <typename T> class Concept{
public:
    virtual void push(T val) = 0;
    virtual T pop() = 0;
};

你脑子里混合了模板和纯虚函数。第一个是编译时间,第二个是运行时间.

模板让您避免为不同的数据类型重复代码,其中纯虚拟成员函数允许您使用从同一类型继承的不同多态接口。 Type erasure 也与虚拟成员函数无关。两个完全不同的东西。

一旦上面的模板被实例化,比如说,int,那么它就等于:

   class Concept{
    public:
        virtual void push(int val) = 0;
        virtual int pop() = 0;
    };

现在这个class是抽象的;你不能实例化它,但你可以继承:

class f1 : public Concept {
    public:
    virtual void push(int val) { ... define it }
    virtual int pop()  { ... define it}
};

class f2 : public Concept {
    public:
    virtual void push(int val) { ... define it }
    virtual int pop()  { ... define it}
    ... more members
};

并以多态方式使用它:

Concept* a = new f1();
Concept* b = new f2();

// dynamic_cast<f1>(a) will return a f1*
// dynamic_cast<f2>(b) will return a f2*

我不认为您真的想要一个接口,其中包含不定数量的具有不同参数的 push 和 pop 方法。我也不认为您希望 Concept 后代有许多不同的实现,并且每种类型都有一个单独的堆栈。 看起来你想要将不同类型的对象压入堆栈然后弹出它们。在这种情况下,它可能是这样的:

struct Container 
{
    template<typename T>
    Container(T t);
    template<typename U>
    U cast();
};

class Stack
{
public:
    virtual void push(Container val) = 0;
    virtual Container pop() = 0;
};

class ConcreteStack : public Stack
{
public:
    void push(Container val);
    Container pop();
};


int main() 
{
    ConcreteStack stack;
    stack.push(25);
    stack.push(std::string("abcd"));

    std::string str = stack.pop().cast<std::string>();
    int num = stack.pop().cast<int>();
}

不幸的是,我没有看到在 pop 时逃避显式类型转换的方法。只有返回类型不同的同名方法不在少数。