C ++使用不同数据类型的相似函数

时间:2019-01-30 05:20:01

标签: c++ templates stack queue

我有两个功能完全相同的功能,除了其中一个功能使用stack进行操作,另一个功能使用queue

void doQueue()
{
    std::queue<int> q;
    ...
    ...
    q.push(someValue);
    ...
    ...
    int tmp = q.front();
    q.pop()
}

void doStack()
{
    std::stack<int> s;
    ...
    ...
    s.push(someValue);
    ...
    ...
    int tmp = s.top();
    s.pop()
}

我想消除重复的代码。由于queue使用front函数检索第一个值,而stack使用top函数,我认为模板可能无法正常工作,因为必须调用具有不同名称的函数

我的另一个想法是创建一个接口,将其作为两个数据结构的包装,并且我可以传递我需要的那个接口。

class Data
{
public:
    virtual void push(const int v) = 0;
    virtual int pop() = 0;
};

class StackData : public Data
{
private:
    std::stack<int> _stack;

public:
    virtual void push(const int v) {_stack.push(v);}
    virtual int pop() 
    {
        int ret = _stack.top();
        _stack.pop();
        return ret;
    }
};


class QueueData : public Data
{
private:
    std::queue<int> _queue;

public:
    virtual void push(const int v) {_queue.push(v);}
    virtual int pop() 
    {
        int ret = _queue.front();
        _queue.pop();
        return ret;
    }
};

void doData(Data& dataType)
{
    ...

    dataType.push(someValue);

    ...

    int tmp = dataType.pop();

}

void doQueue()
{
    QueueData queueData;
    doData(queueData);
}

void doStack()
{
    StackData stackData;
    doData(stackData);
}

但是我认为应该有一种更简便,更好的方法来执行此操作。

1 个答案:

答案 0 :(得分:2)

这是一种方法-一种包装模板,其中部分专门针对基础容器类型:

#include <stack>
#include <queue>


template<class Container>
struct generic_sequence_ops;

template<class T, class UnderlyingContainer>
struct generic_sequence_ops<std::stack<T, UnderlyingContainer>>
{
    using container_type = std::stack<T, UnderlyingContainer>;
    using value_type = typename container_type::value_type;

    generic_sequence_ops(container_type& c) : c(c) {}

    void add_one(value_type v)
    {
        c.push(std::move(v));
    }

    void remove_one()
    {
        c.pop();
    }

    value_type& current()
    {
        return c.top();
    }

    container_type& c;
};

template<class T, class UnderlyingContainer>
struct generic_sequence_ops<std::queue<T, UnderlyingContainer>>
{
    using container_type = std::queue<T, UnderlyingContainer>;
    using value_type = typename container_type::value_type;

    generic_sequence_ops(container_type& c) : c(c) {}

    void add_one(value_type v)
    {
        c.push(std::move(v));
    }

    void remove_one()
    {
        c.pop();
    }

    value_type& current()
    {
        return c.back();
    }

    container_type& c;
};

template<class Container>
auto make_generic_sequence_ops(Container& cont)
{
    return generic_sequence_ops<std::decay_t<Container>>(cont);
}

template<class Container>
int doContainer(Container& cont)
{
    auto s = make_generic_sequence_ops(cont);

    s.add_one(6);
    int val = s.current();
    s.remove_one();
    return val;
}

int main()
{
    std::queue<int> q;
    std::stack<int> s;

    doContainer(q);
    doContainer(s);
}