2010-02-26 51 views
13
class A 
{ 
}; 

template <typename A, int S> 
class B 
{ 
public: 
     static int a[S]; 

     B() 
     { 
       a[0] = 0; 
     } 
}; 

template<> int B<A, 1>::a[1]; 

int main() 
{ 
     B<A, 1> t; 
     t; 
} 

Nó biên dịch thuộc GCC 4.1, nhưng không liên kết:thành viên khởi tạo tĩnh cho chuyên lớp mẫu

static.cpp:(.text._ZN1BI1ALi1EEC1Ev[B<A, 1>::B()]+0x5): undefined reference to `B<A, 1>::a' 

Tôi muốn giữ initialisation chuyên nếu có thể, kể từ mảng nắm giữ một số dữ liệu cụ thể cho loại.

+1

Sẽ không B :: chỉ có 1 phần tử? Vì vậy, bằng cách tham chiếu B :: a [1], bạn có đang lập chỉ mục vượt quá giới hạn của mảng không? – Dathan

+0

Tôi không thấy 'typename A' đang làm * bất cứ thứ gì * trong đó. –

Trả lời

1

Bạn cần phải chỉ định giá trị cho nó.

template<> int B<A, 1>::a[1] = {0}; 
+1

Không phải là mẫu <> int B :: a = {0}? – Dathan

+0

@Dathan: Tại sao? Mã của bạn là 'lỗi: tuyên bố xung đột 'int B :: a''. – kennytm

+1

@Dathan, khai báo đó sẽ chuyên một thành viên số nguyên chứ không phải mảng. –

0

Nó không liên kết vì bạn không xác định giá trị cho thành viên tĩnh của mình.

template<> int B<A, 1>::a[] = { 0 }; 

Edit:

Btw: Tôi sẽ luôn luôn thích sử dụng boost :: array thay vì nguồn gốc C-loại:

class A { }; 

template <typename A, std::size_t S> 
class B 
{ 
public: 
    static boost::array<int, S> a; 

    B() { a[0] = 0; } 
}; 

template<> boost::array<int, 1> B<A, 1>::a = { }; 

int main() 
{ 
    B<A, 1> t; 
    cout << t.a[0] << endl; 
} 
31

Đối với chuyên ngành thành viên tĩnh, nếu bạn don 't khởi tạo thành viên, nó được thực hiện như là một chuyên ngành khai báo , mà chỉ nói "Ồ, không khởi tạo thành viên từ mẫu chính, bởi vì có một đặc biệt ized định nghĩa ở một nơi khác ". Cần lưu ý rằng định nghĩa sẽ xuất hiện trong tệp .cpp (nếu không, bạn sẽ kiếm được điều ngược lại: nhiều định nghĩa) và khai báo không có bộ khởi tạo vẫn nên được đặt trong tệp tiêu đề.

Bây giờ cú pháp đúng thực sự là những điều sau đây, và nó nên không xuất hiện trong một tập tin tiêu đề, nhưng trong một tập tin .cpp

template<> int B<A, 1>::a[1] = { }; 

Sau đây vẫn sẽ xuất hiện trong một tập tin tiêu đề:

template<> int B<A, 1>::a[1]; 

Điều này sẽ đóng vai trò là chuyên môn khai báo .


Từ đó, nó sau đó bạn không thể chuyên một thành viên mà chỉ có một constructor mặc định và không copyable, bởi vì bạn sẽ cần cú pháp sau:

// needs a copy constructor! 
template<> Type Class<Arguments>::member = Type(); 

C++ 0x sửa chữa này:

// doesn't anymore need a copy constructor 
template<> Type Class<Arguments>::member{}; 

Đối với những người Standardese giữa chúng ta, đây là những dấu ngoặc kép:

14.7.3/6:

If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

14.7.3/15:

An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization.

template<> X Q<int>::x; 

This is a declaration regardless of whether X can be default initialized (8.5). ]

3.2/3:

Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.

3.2/5:

There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program [...]

Hạn chế của việc này để "mà một số thông số mẫu không được chỉ định" có nghĩa là chúng tôi được phép làm những điều sau đây, đặt nó thành một tiêu đề (do đó có thể có nhiều định nghĩa về chuyên môn này):

template<> template<typename T> 
Type OuterClass<int>::InnerClass<T>::StaticMember = 0; 

Trong trường hợp của bạn, bạn có tất cả các tham số được chỉ định, làm cho nó không được bao phủ bởi quy tắc defintion một cho phép nhiều định nghĩa.

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