【问题标题】:Template Specialization for T -> std::vector<T>T -> std::vector<T> 的模板特化
【发布时间】:2015-06-03 17:29:33
【问题描述】:

我有一个模板类方法

template<class T>
T pop<T>();

现在我想做一个模板特化如下,

template<class T>
std::vector<T> pop<T>();

我可以做以下没问题,

template<>
std::vector<int> classname::pop<std::vector<int>>();

但我仍然需要将类型保留为模板参数。我该如何做到这一点?

【问题讨论】:

标签: c++ templates


【解决方案1】:

在我的脑海中,我通常使用一个成员结构来解决它:

template <typename T>
struct pop_impl {
    static T pop(classname& x); // normal function
};

template <typename T>
struct pop_impl<std::vector<T>> {
    static std::vector<T> pop(classname& x); // specialized for std::vector<T>
};

template <typename T>
T classname::pop() { return pop_impl<T>::pop(*this); }

【讨论】:

  • 您肯定需要将*this 传递给那些静态函数吗?
  • @JonathanWakely 好吧,在 OP 的示例中,该函数没有参数。
  • 对,这正是我的意思。不过,我不能再投票了,就像我已经做过的那样:)
【解决方案2】:

此答案最初由Austin Salgat 在问题Template Specialization for T -> std::vector 的正文中提供(根据CC BY-SA 3.0 许可发布),为了遵守网站的问答,已将其作为答案移至此处格式。


感谢 Piotr,我最终使用了标签调度。下面是代码 对于我最终做了什么,

// The public method that is accessed by class.push<std::vector<int>>(12);
template<class T>
void push(T data) {
    push(tag<T>(), data);
}

// The private method that calls the actual vector push for vector types
template<class T>
void push(tag<std::vector<T>>, std::vector<T> const& data_vector) {
    push_vector(data_vector);
}

// The actual implementation
template<class T>
void push_vector(std::vector<T> const& data_vector) {
// Actual implementation in here
}

【讨论】:

    【解决方案3】:

    一个可能的解决方案是这样实现的非成员函数

    template <class T>
    struct classname_pop
    {
        static T pop(classname &obj) { return obj.pop() ;}
    }
    
    template <class T>
    struct classname_pop<std::vector<T>>
    {
       static std::vector<T> pop(classname &obj) {obj.specialized_pop() ;}
    }
    
    template <class T>
    T classname_pop(classname &obj)
    {
       return classname_pop_t<T>::pop() ;
    }
    

    【讨论】:

    • 这个想法很好......但是答案中有很多语法错误,很难理解。你写了classname_pop,然后写了classname_pop_t,你调用了同样的函数,classname_pop(应该是classname::pop?)。当然应该是classname::pop()(没有参数)调用classname_pop::pop(*this)(有一个参数)?非专业人士应致电return obj.pop_unspecialized&lt;T&gt;() ?
    【解决方案4】:

    您需要一个临时代理来分派不同的结果:

    例子:

    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    class Stack
    {
        private:
        std::vector<int> m_data;
    
        class Pop {
            friend class Stack;
    
            public:
            Stack& stack;
    
            Pop(Stack& stack)
            :   stack(stack)
            {}
    
            private:
            Pop(const Pop&) = default;
            Pop& operator = (const Pop&) = default;
    
            public:
            operator int () {
                std::vector<int>& data = stack.m_data;
                int result = -1;
                if( ! data.empty()) {
                    result = data.front();
                    data.erase(data.begin());
                }
                return result;
            }
    
            operator std::vector<int> () {
                std::vector<int>& data = stack.m_data;
                std::size_t size = std::min(data.size(), std::size_t(3));
                std::vector<int> result(data.begin(), data.begin() + size);
                data.erase(data.begin(), data.begin() + size);
                return result;
            }
        };
    
        public:
        Stack()
        :   m_data( {0, 1, 2, 3, 4, 5, 6, 7, 8} )
        {}
    
        const std::vector<int>& data() const { return m_data; }
        Pop pop() { return Pop(*this); }
    };
    
    int main()
    {
        Stack stack;
        int i = stack.pop();
        std::vector<int> v = stack.pop();
        std::cout << "i = " << i << '\n';
        std::cout << "v = {";
        for(auto i : v)
            std::cout << i;
        std::cout << "}\n";
    }
    

    免责声明:我认为代码完全没用(如果 pop() 只返回单个值而 pop(std::size_t) 转换为不同的容器,它可能会变得有用,其中Pop 的析构函数正在擦除)。

    【讨论】:

      猜你喜欢
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多