如何使用模板推广容器适配器?

时间:2016-12-19 18:01:36

标签: c++ templates stack queue conversion-operator

我有以下课程:

#include <set>
#include <stack>
#include <queue>
#include <string>

template <typename T>
class MySet
{
    public:
        const std::stack<T> data() const
        {
            std::stack<T> other_cont ( typename std::stack<T>::container_type ( cont.begin(), cont.end() ) );
            return other_cont;
        }

    private:
        std::set<T> cont;
};

以下代码:

MySet<std::string> a;
MySet<int> b;

const std::stack<std::string> s = a.data();
const std::queue<int> q = b.data();

我想使用一个模板化成员函数来初始化任何适配器类型。 到目前为止,它只适用于stackqueue,我无法弄清楚如何使用模板进行推广。

这是我尝试过的:

template <template <typename> typename M>
const M<T> data() const
{
    M<T> other_cont ( typename M<T>::container_type ( cont.begin(), cont.end() ) );
    return other_cont;
}

编译器说它无法推断出模板参数M

2 个答案:

答案 0 :(得分:3)

简单的方法是使用转换运算符:

#include <set>
#include <stack>
#include <queue>
#include <string>

template <typename T>
class MySet
{
    public:
        template <typename O, typename = typename O::container_type>
        operator O() const
        {
            return O(typename O::container_type(cont.begin(), cont.end()));
        }

    private:
        std::set<T> cont;
};

使用这种方法,符号是不同的:没有使用data()成员:

int main()
{
    MySet<std::string> s;
    std::stack<std::string> st = s;
    std::queue<std::string> qu = s;
} 

如果您想使用data()成员并从结果中获取不同类型,则您需要返回一个代理,该代理会在访问时进行适当转换:

#include <set>
#include <stack>
#include <queue>
#include <string>

template <typename T>
class MySet
{
    public:
        class Proxy {
            std::set<T> const* set;
        public:
            Proxy(std::set<T> const* s): set(s) {}
            template <typename O, typename = typename O::container_type>
            operator O() const
            {
                return O(typename O::container_type(set->begin(), set->end()));
            }
        };

        Proxy data() const { return Proxy{&this->cont}; }
    private:
        std::set<T> cont;
};

int main()
{
    MySet<std::string> s;
    std::stack<std::string> st = s.data();
    std::queue<std::string> qu = s.data();
} 

答案 1 :(得分:3)

考虑您的主叫代码:

a.data()

data()没有任何内容可以推断出它的返回类型。你必须明确地明确它,如:

a.data<std::stack>()

但是,根据您的评论,您无法修改使用代码。您可以做的是使用模板类型转换运算符:

template <typename M>
operator M() const
{
    M other_cont ( typename M::container_type ( cont.begin(), cont.end() ) );
    return other_cont;
}

为了保持代码未经编辑,您的data方法应该返回此对象:

const MySet<T> data() const
{
    return *this;
}