使一个类成为函数族的朋友



我有一个类模板

template <class Key, class T, class Hash, template <class> class Allocator>
class Table; 

和函数模板

template <class Key, class T, class DevHash, template <class> class DevAllocator, class HostHash, template <class> class HostAllocator>
void copyTableToHost(const Table<Key, T, DevHash, DevAllocator> &table, Table<Key, T, HostHash, HostAllocator> &hostTable);

现在我想授予copyTableToHost()tablehostTable的私有成员的访问权限。为了做到这一点,我在Table类中做了一个朋友声明:

template <class DevHash, template <class> class DevAllocator, class HostHash, template <class> class HostAllocator>
friend void copyTableToHost<Key, T, DevHash, DevAllocator, HostHash, HostAllocator>(const Table<Key, T, DevHash, DevAllocator> &table, Table<Key, T, HostHash, HostAllocator> &hostTable);

我的理由是我不需要在这里指定KeyT作为模板参数,因为它们对于给定的专门化是固定的。同时,给定的专门化需要与整个函数类成为朋友,这些函数的选择不同于DevHash,DevAllocator,HostHashHostAllocator(我不确定模板模板参数在这里是否会把事情搞砸…)。

我得到的错误形式是member Table<Key, T, Hash, Allocator>::[member name] is inaccessible,这使我相信友元声明没有按预期工作。

如果你想让它成为一个免费的friend函数模板,一个选择是把它的所有实例都变成好友:

template <class Key, class T, class Hash, template <class> class Allocator>
class Table {
template <class K, class Ty, 
class Hash1, template <class> class Allocator1,
class Hash2, template <class> class Allocator2>
friend void copyTableToHost(const Table<K, Ty, Hash1, Allocator1>& table,
Table<K, Ty, Hash2, Allocator2>& hostTable);
int x = 0; // private
};
template <class Key, class T,
class Hash1, template <class> class Allocator1,
class Hash2, template <class> class Allocator2>
void copyTableToHost(const Table<Key, T, Hash1, Allocator1>& table,
Table<Key, T, Hash2, Allocator2>& hostTable)
{
hostTable.x = table.x; // now ok
}

另一种选择是使用迭代器并在成员函数中填充表,该成员函数接受迭代器,并要求它们被解引用到std::pair<Key, T>-或用于打包每个<Key, T>的任何类模板中。它可以像这样:

#include <type_traits>
#include <iterator>
template <class Key, class T, class Hash, template <class> class Allocator>
class Table {
public:
template<class It>
requires std::is_same_v<typename std::iterator_traits<It>::value_type,
std::pair<Key, T>>
void copyFrom(It first, It last) {
// copy from `first` to `last`
}
};

最新更新