4

通常の 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です。そうでない場合は否定的にテストされ、はいの場合、つまり関数シグネチャが一致する場合、そこでインスタンス化できなくても、肯定的にテストされます。

4

1 に答える 1

0

いいえ、SFINAE は過負荷の解決中にのみ有効です。解決が行われ、コンパイラーが関数 SFINAE のインスタンス化を開始すると、終了です。

編集:関数のアドレスを取得すると、インスタンス化されます。

于 2010-06-18T17:54:07.913 に答える