使用 SFINAE 有条件地解析分配器成员



我正在为列表数据结构编写构造函数。

template <class T, class Allocator = std::allocator<T>>
class list {
...
}

该类采用Allocator模板参数,如果未提供,则默认为std::allocator。由于 C++11 分配器可能具有状态,因此默认构造函数也采用分配器对象。

//    *** CONSTRUCTORS ***
explicit list(const Allocator& alloc = Allocator()): alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0) {
if(std::is_same<Allocator, customAllocator<T>>::value) {
std::cout << "****" << std::endl;
std::cout << alloc.member_ << std::endl;
std::cout << alloc_.member_ << std::endl;
std::cout << "****" << std::endl;
}
}

当提供包含"member_"的自定义分配器时,以下行将执行而不会失败。

然而,当一个std::allocator被传递时,编译器抱怨分配器中没有成员'member_'是可以理解的。

但是,有没有办法在提供自定义分配器时打印std::cout行,而在提供std::allocator(或任何没有"member_"的分配器(时不打印?

谢谢

您的问题是在 C++17 中引入的典型问题if constexpr

if constexpr (std::is_same<Allocator, customAllocator<T>>::value) {
std::cout << "****" << std::endl;
std::cout << alloc.member_ << std::endl;
std::cout << alloc_.member_ << std::endl;
std::cout << "****" << std::endl;
}

在 C++17 之前,if constexpr不可用,因此当std::is_same测试为 false 时std::cout << alloc.member_也会编译。

因此,您必须以某种方式开发两种不同的功能:一种用于customAllocator,另一种用于其他功能。

我想你可以尝试如下(注意:代码未测试(

template <typename T>
void printMember (customAllocator<T> const & a)
{ 
std::cout << "****" << std::endl;
std::cout << alloc.member_ << std::endl;
std::cout << alloc_.member_ << std::endl;
std::cout << "****" << std::endl;
}
template <typename A>
void printMember (A const &)
{ }
explicit list(const Allocator& alloc = Allocator())
: alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0)
{ printMember(alloc); }

如果需要,还可以为具有member_成员的分配器编写一个函数,为其他成员编写一个函数。

如下所示(注意:代码未测试(

template <typename A>
auto printMember (A const & a, int)
-> decltype( a.member_, void() )
{ 
std::cout << "****" << std::endl;
std::cout << alloc.member_ << std::endl;
std::cout << alloc_.member_ << std::endl;
std::cout << "****" << std::endl;
}
template <typename A>
void printMember (A const &, long)
{ }
explicit list(const Allocator& alloc = Allocator())
: alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0)
{ printMember(alloc, 0); }

最新更新