2012-04-09 14 views
10

Là một phần của một lớp đặc điểm cho một chương trình lớn hơn, tôi đã cố gắng tạo một biến lớp tĩnh có thể có một giá trị khác nhau tùy thuộc vào loại mà mẫu lớp kèm theo được khởi tạo.Lỗi trình biên dịch G ++ hoặc mã bị lỗi? : "định nghĩa mẫu không mẫu"

tôi đã đơn giản hóa các mã có liên quan để tạo ra một trần xương ví dụ về những gì tôi đang nói về:

#include <iostream> 
#include <string> 
#include <type_traits> 

template <class T, class Enable = void> 
struct Foo; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T> 
struct Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
> 
{ 
    static std::string message; 
}; 

template <class T, class Enable> 
std::string Foo<T, Enable>::message; 

Với GCC 4.6, điều này mang lại một lỗi biên dịch: template definition of non-template ‘std::string Foo<T, Enable>::message. Vấn đề xảy ra vì hai dòng cuối cùng, nơi tôi chỉ xác định biến tĩnh std::string Foo<T, Enable>::message.

Tôi đang bối rối vì sao điều này xảy ra. Lỗi trình biên dịch biến mất nếu tôi bỏ qua hai dòng cuối cùng (nhưng tất nhiên là gây ra lỗi liên kết.) Đây có phải là lỗi trình biên dịch với GCC không?

+2

+1 cho "ví dụ về xương trần". http://sscce.org/. –

+0

Bạn cần phải bao gồm

+0

@Vaughn, đó không phải là vấn đề ở đây, nhưng tôi đã cập nhật đoạn mã. – Channel72

Trả lời

10

này chỉ hoạt động khi các thông số mẫu của bạn phù hợp với chuyên môn hóa từng phần:

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_integral<T>::value>::type 
>::message; 

template <class T> 
std::string Foo<T, 
    typename std::enable_if<std::is_floating_point<T>::value>::type 
>::message; 

này được quy định tại phần 14.5.4.3 của tiêu chuẩn C++ 03. Ý tưởng là một chuyên môn hóa một phần là một mẫu mới và các tham số mẫu của các thành viên được định nghĩa bên ngoài phải khớp với các tham số mẫu của định nghĩa lớp để nó biết khuôn mẫu mà thành viên đi kèm.

Trong ví dụ của bạn, quy tắc tránh xác định thành viên thư cho các loại không phải là điểm tách rời hoặc dấu phẩy động.

+0

Tại sao nó chỉ hoạt động trong trường hợp đó? – SirGuy

+0

Có một số lý do mà một định nghĩa duy nhất không hoạt động ở đây không? Đây có phải là một cái gì đó bắt buộc bởi tiêu chuẩn C++, hoặc một quirk trong G + +? – Channel72

+0

@GuyGreer: Tôi đoán vì trường _message_ tĩnh không được khai báo cho mẫu chung (chỉ dành cho một số chuyên ngành). không thể xác định thứ gì đó không được khai báo – user396672

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