通常の 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 の割り当て関数をインスタンス化しようとし、不完全な型の sizeof が関数本体内で使用されていることを検出し、ハード エラーを引き起こします。などのように使用する際にアロケートの実装を分けて別々にインクルードすればエラーは発生しないようです
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
です。そうでない場合は否定的にテストされ、はいの場合、つまり関数シグネチャが一致する場合、そこでインスタンス化できなくても、肯定的にテストされます。