Problem with incomplete type while trying to detect existence of a member function

Posted by abir on Stack Overflow See other posts from Stack Overflow or by abir
Published on 2010-06-17T12:07:57Z Indexed on 2010/06/17 12:13 UTC
Read the original article Hit count: 182

Filed under:
|

I was trying to detect existence of a member function for a class where the function tries to use an incomplete type. The typedef is

struct foo;
typedef std::allocator<foo> foo_alloc;  

The detection code is

struct has_alloc
{
  template<typename U,U x> struct dummy;
  template<typename U>
  static char check(dummy<void* (U::*)(std::size_t),&U::allocate>*);
  template<typename U>
  static char (&check(...))[2];
  const static bool value = (sizeof(check<foo_alloc>(0)) == 1);
};

So far I was using incomplete type foo with std::allocator without any error on VS2008. However when I replaced it with nearly an identical implementation as

template<typename T>
struct allocator
{
  T* allocate(std::size_t n)
 {
   return (T*)operator new (sizeof(T)*n);
 }
};

it gives an error saying that as T is incomplete type it has problem instantiating allocator<foo> because allocate uses sizeof. GCC 4.5 with std::allocator also gives the error, so it seems during detection process the class need to be completely instantiated, even when I am not using that function at all. What I was looking for is void* allocate(std::size_t) which is different from T* allocate(std::size_t).

My questions are (I have three questions, but as they are correlated , so I thought it is better not to create three separate questions).

  1. Why MS std::allocator doesn't check for incomplete type foo while instantiating? Are they following any trick which can be implemented ?
  2. Why the compiler need to instantiate allocator<T> to check the existence of the function when sizeof is not used as sfinae mechanism to remove/add allocate in the overload resolutions set? It should be noted that, if I remove the generic implementation of allocate leaving the declaration only, and specialized it for foo afterwards such as

    struct foo{}; template<> struct allocator { foo* allocate(std::size_t n) { return (foo*)operator new (sizeof(foo)*n); } };

    after struct has_alloc it compiles in GCC 4.5 while gives error in VS2008 as allocator<T> is already instantiated and explicit specialization for allocator<foo> already defined.

  3. Is it legal to use nested types for an std::allocator of incomplete type such as typedef foo_alloc::pointer foo_pointer; ? Though it is practically working for me, I suspect the nested types such as pointer may depend on completeness of type it takes. It will be good to know if there is any possible way to typedef such types as foo_pointer where the type pointer depends on completeness of foo.

NOTE : As the code is not copy paste from editor, it may have some syntax error. Will correct it if I find any. Also the codes (such as allocator) are not complete implementation, I simplified and typed only the portion which I think useful for this particular problem.

© Stack Overflow or respective owner

Related posts about c++

Related posts about sfinae