2015-04-10 14 views
8

Ok, tôi đang làm việc với g ++ 4.8.2 và có đoạn mã sau (hơi dài) nhận được thông báo lỗi về loại không đầy đủ. Tôi đã giảm mã để một đoạn nhỏ để đưa vào đây và có thể được biên dịch trực tiếp:Sizeof thất bại trong mẫu mặc dù tất cả các loại được xác định

#include <cstdlib> 

struct S 
{ 
    void method(){} 
}; 


template<size_t sz, size_t tot> 
class genpool 
{ 
}; 

template <class T> 
class mempool 
{ 
private: 
    genpool<sizeof(T), 10*sizeof(T)> p; 
}; 


template <class obj, class mthd> 
class functor 
{ 
private: 
    static mempool<functor<obj, mthd> > pool; 
}; 

template <class obj, class mthd> 
mempool<functor<obj, mthd> > functor<obj, mthd>::pool; 

int main() 
{ 
    typedef void (S::*m)(); 
    typedef functor<S, m> fctr; 

    fctr f; 
} 

Thông điệp biên dịch lỗi là:

g++ jj.C 
jj.C: In instantiation of ‘class mempool<functor<S, void (S::*)()> >’: 
jj.C:30:30: required from ‘class functor<S, void (S::*)()>’ 
jj.C:37:8: required from here 
jj.C:18:17: error: invalid application of ‘sizeof’ to incomplete type ‘functor<S, void (S::*)()>’ 
    genpool<sizeof(T), 10*sizeof(T)> p; 
       ^

Compilation exited abnormally with code 1 at Thu Apr 9 18:50:06 

Rõ ràng, mẫu functor được định nghĩa ở trên và tất cả các đối số để functor đã được xác định rõ ràng. Điều này dường như hàm ý rằng hàm sizeof cần được xác định rõ. Có điều gì tôi thiếu ở đây không?

--Ron

Trả lời

0

Tôi không nghĩ bạn có thể làm điều đó, bởi vì bạn có định nghĩa đệ quy. Ví dụ: bạn không thể thực hiện việc này:

#include <cstdlib> 

class B; 

class A 
{ 
    B b; 
}; 

class B 
{ 
    A a; 
}; 

int main() 
{ 
     A x; 
} 

Cách duy nhất để làm cho một trong các thành viên là con trỏ thay vì một cá thể.

1

Định nghĩa của bạn về functor là đệ quy. Nó yêu cầu trình biên dịch biết kích thước của loại functor trong khi xác định loại functor. Bạn có thể tạo ra chính xác cùng một vấn đề với mã này:

template <class A> 
class B { 
public: 
    static const int szA = sizeof(A); 
}; 

template <class A> 
class C { 
public: 
    static B<C<A> > b; 
}; 

int main() { 
    C<int> c; 
} 

Tùy thuộc vào những gì ứng dụng của bạn, bạn sẽ có thể làm những gì bạn muốn sử dụng type traits.

+0

Tôi nghĩ các thành viên dữ liệu tĩnh sẽ không góp phần vào kích thước của một lớp học vì vậy không nên có bất kỳ đệ quy ở đây ... –

+0

Nó không có vấn đề gì kích thước của lớp cuối cùng sẽ được. Tại thời điểm bạn khai báo thành viên tĩnh, trình biên dịch không biết kích thước của lớp là vì nó chưa hoàn thành khai báo lớp. – Mokosha

1

Vào thời điểm đó bạn khai báo poolbên của functor, bạn vẫn định lớp functor, vì vậy loại functor vẫn chưa đầy đủ.

này tương tự để chuyển tiếp tờ khai:

class functor; 
functor func; <<-incomplete here 
functor *ptr; <<-pointer is fine 
class functor 
{ 
    functor func; <<-incomplete again 
}; 
functor func; <<-now complete definition, ok 
6

Vấn đề là trình biên dịch đang nỗ lực để nhanh chóng mempool<> trước khi nó instantiates functor<>. Điều này là do trình biên dịch cảm thấy nó cần để có thể xác định các thành viên tĩnh functor<>::pool đầu tiên trước khi functor<> chính nó được coi là hoàn toàn xác định.

Giải pháp thay thế là trả về một mempool<> & từ một hàm thành viên tĩnh.

template <class obj, class mthd> 
class functor 
{ 
private: 
    static mempool<functor> & get_pool() { 
    static mempool<functor> pool; 
    return pool; 
    } 
}; 

//template <class obj, class mthd> 
//mempool<functor<obj, mthd> > functor<obj, mthd>::pool; 

Điều này có nghĩa là không được hoàn thành cho đến khi sau functor<> được khởi tạo. (Trên thực tế, một phương thức của một mẫu không được khởi tạo trừ khi có mã thực sự gọi nó.) Khi phương thức tĩnh được gọi, functor<> chính nó đã hoàn thành, vì vậy đối tượng tĩnh trong functor<>::get_pool có thể được khởi tạo đúng cách.

Là một mặt lưu ý, đó là có thể chấp nhận để vượt qua một loại không đầy đủ như một tham số để một mẫu, nhưng mẫu có hạn chế về những gì nó thực sự có thể làm với một loại không đầy đủ. Mọi thứ đều ổn nếu mẫu chỉ yêu cầu một tham chiếu hoặc con trỏ đến loại cho sự khởi tạo của nó.

+0

Tuyệt vời! Điều này làm việc hoàn hảo. –

Các vấn đề liên quan