假设我有一个<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
中将非模板函数声明为朋友,但我定义的是函数模板。那么这样做的正确方法是什么?
答案 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方法有更多侵入性指针用法时创建不明确的重载。