Я хочу обнаружить существование определенной функции-члена для класса, используя обычный трюк 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, компилятор пытается создать экземпляр функции allocate для std :: allocator и находит, что 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
. Если нет, это будет отрицательный результат, и если да, то есть. если сигнатура функции совпадает, даже если ее нельзя создать там, проверьте положительный результат.