Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Code fails to compile

askoufyin
Beginner
501 Views
The following code fails to compile with diagnostic message

test.cpp
test.cpp(13): error: incomplete type is not allowed
T items[T_NUMITEMS];
^
detected during instantiation of class TypeAllocator [with T=Foo, T_NUMITEMS=64U]" at line 81

What am I doing wrong and why compiler thinks that Foo class is incomplete type?

Compiler version 11.1 build 20090930
[cpp]#include 
#include 


#define FOO_PAGE_SIZE 64


template  
class TypeAllocator {
protected:
    typedef struct _s_typeblk {
        struct _s_typeblk *next;
        T items[T_NUMITEMS];
    } _TypeBlock;
protected:
    _TypeBlock *_head;
    T *_free;
protected:
    T *setupFreeChain(_TypeBlock *blk) {
        int i;

        for(i=T_NUMITEMS-1; i>0; --i)
            *reinterpret_cast(&blk->items[i-1]) = &blk->items;

        *reinterpret_cast(&blk->items[T_NUMITEMS-1]) = NULL;

        return blk->items;
    }
public:
    TypeAllocator(): _head(0), _free(0) {
    }

    ~TypeAllocator() {
        _TypeBlock *temp;

        while(_head) {
            temp = _head;
            _head = _head->next;
            ::free(temp);
        }
    }

    T *alloc() {
        _TypeBlock *nb;
        T *item;

        if(!_free) {
            if((nb = (_TypeBlock *)::malloc(sizeof(_TypeBlock)))==NULL)
                return NULL;

            nb->next = _head;
            _head = nb;

            _free = setupFreeChain(nb);
        }

        item = _free;
        _free = *reinterpret_cast(_free); 

        return item;
    }

    void free(T *ptr) {
        _TypeBlock *blk;

        for(blk=_head; blk; blk=blk->next)
            if(ptr >= blk->items && ptr <= &blk->items[T_NUMITEMS-1])
                break;

        if(blk) {
            *reinterpret_cast(ptr) = _free;
            _free = ptr;
        }
    }
};


class Foo
{
protected:
    static TypeAllocator allocator;
public:
    void *operator new(size_t cb) {
          return (void *)allocator.alloc();
    }
    void operator delete(void *ptr, size_t cb) {
          allocator.free((Foo *)ptr);
    }
};


TypeAllocator Foo::allocator;


int main()
{
    Foo *foo = new Foo();
    delete foo;
}
[/cpp]

0 Kudos
3 Replies
JenniferJ
Moderator
501 Views
Thanks for attaching a testcase.

It seems a compiler bug to me. VC2008 compiles fine. I'll file a bug report to the compiler engineer team and will let you know if there's a work-around or any progress.

Thanks again!
Jennifer
0 Kudos
JenniferJ
Moderator
501 Views
Hello,

Our engineer found a work-around for this case.

Please move the struct-type to the outside of the class template like following:

[cpp]#include 
#include 


#define FOO_PAGE_SIZE 64
template  
struct _s_typeblk {
        struct _s_typeblk *next;
        M items[M_SIZE];
};


template  
class TypeAllocator {
protected:
	typedef _s_typeblk _TypeBlock;
protected:
    _TypeBlock *_head;
    T *_free;
protected:
    T *setupFreeChain(_TypeBlock *blk) {
        int i;

        for(i=T_NUMITEMS-1; i>0; --i)
            *reinterpret_cast(&blk->items[i-1]) = &blk->items;

        *reinterpret_cast(&blk->items[T_NUMITEMS-1]) = NULL;

        return blk->items;
    }
public:
    TypeAllocator(): _head(0), _free(0) {
    }

    ~TypeAllocator() {
        _TypeBlock *temp;

        while(_head) {
            temp = _head;
            _head = _head->next;
            ::free(temp);
        }
    }

    T *alloc() {
        _TypeBlock *nb;
        T *item;

        if(!_free) {
            if((nb = (_TypeBlock *)::malloc(sizeof(_TypeBlock)))==NULL)
                return NULL;

            nb->next = _head;
            _head = nb;

            _free = setupFreeChain(nb);
        }

        item = _free;
        _free = *reinterpret_cast(_free); 

        return item;
    }

    void free(T *ptr) {
        _TypeBlock *blk;

        for(blk=_head; blk; blk=blk->next)
            if(ptr >= blk->items && ptr <= &blk->items[T_NUMITEMS-1])
                break;

        if(blk) {
            *reinterpret_cast(ptr) = _free;
            _free = ptr;
        }
    }
};


class Foo
{
protected:
    static TypeAllocator allocator;
public:
    void *operator new(size_t cb) {
          return (void *)allocator.alloc();
    }
    void operator delete(void *ptr, size_t cb) {
          allocator.free((Foo *)ptr);
    }
};


TypeAllocator Foo::allocator;


int main()
{
    Foo *foo = new Foo();
    delete foo;
}
[/cpp]

0 Kudos
askoufyin
Beginner
501 Views
Thank you very much! It works as intended now.
0 Kudos
Reply