我想使用通常的 SFINAE 技巧来检测一个类的特定成员函数的存在。
template<typename T>
struct has_alloc
{
template<typename U,U x>
struct dummy;
template<typename U>
static char test(dummy<void* (U::*)(std::size_t),&U::allocate>*);
template<typename U>
static char (&test(...))[2];
static bool const value = sizeof(test<T>(0)) ==1;
};
应该注意的是,这会检测到一种不同类型的分配器,它具有void* allocate(std::size_t)
非标准的成员函数(可能是一些原始内存分配器)。
接下来,我有一个不完整的类型和一个用于该不完整类型的 std::allocator。
struct test;
typedef std::allocator<test> test_alloc;
我正在检查 test_alloc 是否是我正在寻找的那个。
struct kind_of_alloc
{
const static bool value = has_alloc<test_alloc>::value;
};
当我“使用”时肯定struct test
会完成,test_alloc
例如
#include "test_def.hpp"//contains the code posted above
struct test{};
void use()
{
test_alloc a;
}
在另一个编译单元中。然而,当 has_alloc 测试发生时,编译器尝试实例化 std::allocator 的 allocate 函数,并发现在函数体内使用了不完整类型的 sizeof,并导致硬错误。如果 allocate 的实现在使用时分开并包含在单独的位置,则似乎不会发生错误,例如
template<typename T>
T* alloc<T>::allocate(std::size_t n)
{
return (T*)operator new(sizeof(T)*n);
}
void use()
{
test_alloc a;
a.allocate(2);
}
并test_def.hpp
包含
template<typename T>
struct alloc
{
T* allocate(std::size_t n);
};
然而,虽然我可以这样做alloc<T>
,但因为不可能std::allocator
分离出实现是不可能的。我正在寻找的是可以测试一个函数是否void* allocate(size_t)
存在于test_alloc
. 如果不是,它将测试为否定,如果是,即如果函数签名匹配,即使它不能在那里实例化,也测试为肯定。