2010-06-16 37 views
99
template<typename T> 
class CConstraint 
{ 
public: 
    CConstraint() 
    { 
    } 

    virtual ~CConstraint() 
    { 
    } 

    template <typename TL> 
    void Verify(int position, int constraints[]) 
    {  
    } 

    template <> 
    void Verify<int>(int, int[]) 
    { 
    } 
}; 

Biên dịch này dưới g ++ cung cấp cho các lỗi sau:chuyên môn Explicit trong phạm vi không gian tên

chuyên môn Explicit trong không gian tên phạm vi 'lớp CConstraint'

Trong VC, nó biên dịch tốt. Bất cứ ai có thể vui lòng cho tôi biết cách giải quyết không?

Trả lời

85

VC++ không tuân thủ trong trường hợp này - các chuyên môn rõ ràng phải ở phạm vi không gian tên. C++ 03, §14.7.3/2:

An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.
An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

Ngoài ra bạn có vấn đề mà bạn không thể chuyên hàm thành viên không chuyên một cách rõ ràng lớp chứa do C++ 03, §14.7 0,3/3, vì vậy một giải pháp sẽ được để cho Verify() mong muốn một, có thể là chuyên ngành, chức năng miễn phí:

namespace detail { 
    template <typename TL> void Verify  (int, int[]) {} 
    template <>   void Verify<int>(int, int[]) {} 
} 

template<typename T> class CConstraint { 
    // ... 
    template <typename TL> void Verify(int position, int constraints[]) { 
     detail::Verify<TL>(position, constraints); 
    } 
}; 
+8

* không hoàn toàn trong trường hợp này *: như thường lệ :)? Các mẫu và VC++ không kết hợp tốt như thế:/ –

+0

Cảm ơn rất nhiều :) – Mark

+5

Nó không tuân theo ý nghĩa rằng nó sẽ cho phép bạn làm điều gì đó mà Standard bình thường không cho phép - đó không phải là vấn đề đối với mã là phù hợp để bắt đầu (bạn viết mã như vậy, phải không? ~). Các vấn đề tuân thủ thực sự là khi nó không biên dịch một cái gì đó mà Standard yêu cầu biên dịch, hoặc sẽ hoạt động khác với những gì được chỉ định. –

74

một cách khác để giải quyết nó là bằng cách ủy quyền cho một chức năng riêng và quá tải chức năng đó. Bằng cách này, bạn vẫn có quyền truy cập vào dữ liệu thành viên của *this và loại tham số mẫu bên ngoài.

template<typename T> 
struct identity { typedef T type; }; 

template<typename T> 
class CConstraint 
{ 
public: 

    template <typename TL> 
    void Verify(int position, int constraints[]) 
    { 
    Verify(position, constraints, identity<TL>()); 
    } 

private: 
    template<typename TL> 
    void Verify(int, int[], identity<TL>) 
    { 

    } 

    void Verify(int, int[], identity<int>) 
    { 

    } 
}; 
+0

Cảm ơn rất nhiều. Tôi đã tìm kiếm điều này cũng như tôi cần phải truy cập này. Ước gì tôi có thể chọn 2 câu trả lời. – Mark

+7

Nếu tôi là bạn, tôi sẽ chọn câu trả lời này. @Johannes: Câu trả lời của bạn chỉ là hoàn hảo, cảm ơn. –

+0

Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn, Johannes Schaub, vì câu trả lời này. – Rethunk

1

Bạn không có thể rõ ràng chuyên mẫu thành viên, nhưng bạn có thể phần chuyên nó. Nếu bạn thêm tham số thứ hai "int dummyParam" và cũng thêm nó vào chuyên môn, nó sẽ làm việc với cả hai trình biên dịch.

Không phải là tôi biết điều này hơn 10 giây trước, nhưng googling trên cùng một lỗi, tôi chạy vào this link và nó làm việc cho chuyên môn mẫu thành viên của tôi.

+1

Bạn không thể chuyên trách một phần chức năng – metamorphosis

4

Thậm chí tốt hơn: bạn có thể kết hợp chuyên môn hóa một phần với các đối số mẫu mặc định. Cách sửa đổi này đối với mã VC++ là nhỏ, bởi vì các cuộc gọi đến chức năng chuyên biệt không cần phải sửa đổi.

template <typename TL, class Dummy=int> 
void Verify(int position, int constraints[]) 
{ 
} 

template <class Dummy=int> 
void Verify<int, Dummy>(int, int[]) 
{ 
} 
+2

Đối số mẫu mặc định không được phép trong C++ 03, chỉ trong C++ 0x/11. – Xeo

+1

Xin lỗi, tôi đã sai: bạn không thể chuyên về một phần chức năng. – vitke

+0

@Xeo: Tôi đoán bạn không được phép sử dụng các chức năng trong C++ 03? "Đối số mẫu mặc định là đối số mẫu (14.3) được chỉ định sau' = 'trong tham số mẫu. Một đối số mẫu mặc định có thể được chỉ định cho bất kỳ loại tham số mẫu nào (loại, loại không, mẫu) Đối số mẫu mặc định có thể được chỉ định trong khai báo mẫu lớp hoặc định nghĩa mẫu lớp ** Đối số mẫu mặc định sẽ không được chỉ định trong khai báo mẫu hàm hoặc mẫu hàm định nghĩa, cũng như trong mẫu tham số-danh sách định nghĩa của một thành viên của một mẫu lớp. ** " –

9

Chỉ cần lấy chuyên môn mẫu bên ngoài khai báo lớp học. gcc không cho phép chuyên môn mẫu nội dòng.

Là một tùy chọn khác, chỉ cần xóa dòng mẫu <> có vẻ phù hợp với tôi.

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