【问题标题】:C++ Similar functions using different data typesC++ 使用不同数据类型的类似函数
【发布时间】:2019-06-23 07:55:02
【问题描述】:

我有两个完全相同的函数,除了其中一个使用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);
}

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

【问题讨论】:

    标签: c++ templates stack queue


    【解决方案1】:

    这是一种方法 - 对底层容器类型进行部分专业化的包装模板:

    #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);
    }
    

    【讨论】:

    • 比我想象的要复杂一点。感谢您的回答!
    • @ReeSSult 它可能比它严格需要的要复杂一些,但我已经尝试为模板框架奠定基础,该框架可以定制以针对任何适当的容器类型提供所需的接口.很高兴能帮上忙:)
    猜你喜欢
    • 2013-04-11
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 2015-07-19
    • 1970-01-01
    相关资源
    最近更新 更多