如何在类模板中将boost :: intrusive_ptr用于私有嵌套类

时间:2016-07-22 23:40:41

标签: c++ templates c++11 boost

假设我有一个<div class="logo"> Name <span class="slogan">Tagline here</span> </div> 类:

list

上面的代码没有编译。错误是template<typename T> class list { ... private: class node { ... private: std::size_t refcount_; // friends of node because accessing private member refcount_ friend void intrusive_ptr_add_ref(const node* p) noexcept; friend void intrusive_ptr_release(const node* p) noexcept; }; // friends of list because accessing private nested class node friend void intrusive_ptr_add_ref(const node* p) noexcept; friend void intrusive_ptr_release(const node* p) noexcept; boost::intrusive_ptr<node> node_{new node}; }; template<typename T> void intrusive_ptr_add_ref(const typename list<T>::node* p) noexcept { ... } template<typename T> void intrusive_ptr_release(const typename list<T>::node* p) noexcept { ... } list<int> xs; // error intrusive_ptr_add_ref(list<int>::node const*)的未定义符号。

我认为问题可能是我在intrusive_ptr_release(list<int>::node const*)list中将非模板函数声明为朋友,但我定义的是函数模板。那么这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这是内联朋友定义闪耀的场合之一:

<强> Live On Coliru

#include <iostream>
#include <boost/intrusive_ptr.hpp>

template<typename T> class list {
    class node {
        std::size_t mutable refcount_;

        // friends of list because accessing private nested class node
        friend void intrusive_ptr_add_ref(node const* p) noexcept {
            p->refcount_ += 1;
        }
        friend void intrusive_ptr_release(node const* p) noexcept {
            if (--p->refcount_)
                return;
            std::cout << "freeing node " << static_cast<void const*>(p) << "\n";
        }
    };

    boost::intrusive_ptr<node> node_{new node};
};

int main() {
    list<int> xs;
}

打印

freeing node 0x19b7c20

或类似的

奖励积分

如果你想要详细的路线,我建议最安全的方法是在Node类型而不是list-element上设置base-template参数(因为部分特殊化不适合功能模板)。

这里的东西也有效:

<强> Live On Coliru

template <typename Node, typename = typename Node::is_my_list_impl_nodetype> void intrusive_ptr_add_ref(Node const*) noexcept;
template <typename Node, typename = typename Node::is_my_list_impl_nodetype> void intrusive_ptr_release(Node const*) noexcept;

template<typename T> class list {
    class node {
        using is_my_list_impl_nodetype = std::true_type;

        std::size_t mutable refcount_;

        // friends of list because accessing private nested class node
        friend void intrusive_ptr_add_ref<node, std::true_type>(node const* p) noexcept;
        friend void intrusive_ptr_release<node, std::true_type>(node const* p) noexcept;
    };

    boost::intrusive_ptr<node> node_{new node};
};

template<typename Node, typename>
void intrusive_ptr_add_ref(Node const* p) noexcept {
    p->refcount_ += 1;
}

template<typename Node, typename>
void intrusive_ptr_release(Node const* p) noexcept {
    if (--p->refcount_)
        return;
    std::cout << "freeing node " << static_cast<void const*>(p) << "\n";
}

整个SFINAE on is_my_list_impl_nodetype是为了防止开放模板在您的翻译单元中使用其他addref / release方法有更多侵入性指针用法时创建不明确的重载。