2013-02-25 27 views
5

Tôi xin lỗi nếu tiêu đề của câu hỏi này ít hữu ích hơn; Tôi không biết một cách gọn gàng để hỏi câu hỏi này mà không đưa ra các ví dụ sau:Đối số mẫu mẫu từ không gian tên khác nhau có phải là một người bạn không?

template <template <class> class Arg> 
class C { 
    typedef C<Arg> type; 
    friend class Arg<type>; 
    public: 
    C() { 
     a_.set(this); 
    } 
    private: 
    int i_; 
    Arg<type> a_; 
}; 

template <class Type> 
class Arg1 { 
    public: 
    void set(Type* t) { 
     t_ = t; 
     t_->i_ = 1; 
    } 
    private: 
    Type* t_; 
}; 

namespace NS { 

    template <class Type> 
    class Arg2 { 
     public: 
     void set(Type* t) { 
      t_ = t; 
      t_->i_ = 2; 
     } 
     private: 
     Type* t_; 
    }; 

} 

Như bạn thấy, Arg2 là một bản sao của Arg1. Tuy nhiên, VS 2008 chỉ cho phép Arg1 được sử dụng như một mẫu đối số:

int main() { 
    C<Arg1> c1; // compiles ok 
    C<NS::Arg2> c2; // error C2248 

    return 0; 
} 

Lỗi này là 'C<Arg>::i_' : cannot access private member declared in class 'C<Arg>'. Mọi thứ hoạt động tốt nếu i_ được đặt ở chế độ công khai, vì vậy đây có vẻ là vấn đề về tình bạn.

Điều gì khiến tuyên bố tình bạn thất bại khi đối số mẫu mẫu nằm trong một không gian tên khác?

+0

Tôi nên thêm rằng cùng một mã cũng không biên dịch trong cả VS 2010 và VS 2012. –

Trả lời

0

Thành viên không gian tên không ảnh hưởng đến tính đủ điều kiện cho tình bạn. Đây là lỗi trình biên dịch.

friendnamespace là các tính năng ngôn ngữ tương tác, do đó, nó không đặc biệt đáng ngạc nhiên khi lỗi xảy ra. Có lẽ nó thực sự kết bạn với một tờ khai chuyển tiếp vô nghĩa trong không gian tên kèm theo, ::Arg2<type>.

+0

Với ý kiến ​​khác (hiện đã bị xóa) chỉ ra rằng clang và gcc biên dịch ví dụ của tôi mà không có lỗi, tôi nghĩ đây là chính xác câu trả lời. –