2016-07-30 11 views
7

Tôi muốn yêu cầu trợ giúp với cú pháp chính xác để khai báo std :: map có mapped_type là một lớp bên trong của một lớp mẫu.Cú pháp chính xác cho trình vòng lặp bản đồ của lớp bên trong của lớp mẫu?

Vui lòng tìm trong mã bên dưới khối # if/# else. Khối "#if 1" có lớp mẫu Bên ngoài chứa lớp bên trong Bên trong. Hàm Outer định nghĩa Func có một bản đồ std có mapped_type là kiểu Inner.

#include <map> 

#if 1 
template<typename C, typename T> 
class Outer 
{ 
    public: 
     Outer(const C& c, const T& t){} 
     virtual ~Outer(){} 

     class Inner 
     { 
      public: 
       Inner(){} 
       Inner(T t){} 
       virtual ~Inner(){} 

      protected: 
       T mT; 
     }; 

     void Func(std::map<C, Inner>& rMap); 

    protected: 
     std::map<C, Inner> mMap; 
}; 

template<typename C, typename T> 
void Outer<C, T>::Func(std::map<C, Outer::Inner>& rMap) 
{ 
    std::map<C, Inner>::iterator iter; 

    for (iter = rMap.begin(); iter != rMap.end(); ++iter) 
    { 
     mMap[iter->first] = iter->second; 
    } 
} 

#else 

class Outer 
{ 
    public: 
     Outer(const int& i, const double& d){} 
     virtual ~Outer(){} 

     class Inner 
     { 
      public: 
       Inner() : mD(0){} 
       Inner(const double d) : mD(d){} 
       virtual ~Inner(){} 

      protected: 
       double mD; 
     }; 

     void Func(std::map<int, Inner>& rMap); 

    protected: 
     std::map<int, Inner> mMap; 
}; 

void Outer::Func(std::map<int, Inner>& rMap) 
{ 
    std::map<int, Inner>::iterator iter; 

    for (iter = rMap.begin(); iter != rMap.end(); ++iter) 
    { 
     mMap[iter->first] = iter->second; 
    } 
} 

#endif 

int main() 
{ 
    return 0; 
} 

Compilation thất bại trong Outer :: Func (...) tại các khai báo của iterator std :: bản đồ, tức là dòng này:

std::map<C, Inner>::iterator iter; 

tôi đã cố gắng nhưng không thể tìm ra những gì sai với dòng mã.

Để so sánh/tương phản, khối "#else" chứa mã không có mẫu có tính chất tương tự. Mã này biên dịch.

Các lỗi biên dịch và phiên bản g ++ là:

>g++ main.cpp 
main.cpp: In member function ‘void Outer<C, T>::Func(std::map<C, Outer<C, T>::Inner, std::less<_Key>, std::allocator<std::pair<const C, Outer<C, T>::Inner> > >&)’: 
main.cpp:31: error: expected ‘;’ before ‘iter’ 
main.cpp:33: error: ‘iter’ was not declared in this scope 

>g++ --version 
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11) 
Copyright (C) 2010 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

Cảm ơn bạn đã giúp đỡ nào.

+0

'typename std :: map :: iterator iter;' – nshct

+0

Có thể trùng lặp [Tại sao và tại sao tôi phải đặt từ khóa "template" và "typename"?] (Http://stackoverflow.com/questions/610245/where-and-why-do-i-có-to-put-the-template-và-typename-keywords) – Oktalist

Trả lời

9

Inner là thành viên của mẫu của bạn Owner<C, T>, nó sẽ trở thành một dependent name. Điều đó làm cho số nhận dạng iterator, trong trường hợp này là thành viên của std::map<C, Inner>, để trở thành tên phụ thuộc.

này buộc bạn phải sử dụng từ khóa typename, theo các quy tắc:

typename std::map<C, Inner>::iterator iter; 
~~~^~~~~ 

Điều này là do trình biên dịch không thể chắc chắn những gì một số cấu trúc bên trong của lớp học của bạn có nghĩa là kể từ khi nó không biết các loại chính xác được sử dụng cho CT chưa:

Bên trong định nghĩa mẫu (cả mẫu lớp và mẫu chức năng), ý nghĩa o f một số cấu trúc có thể khác nhau từ một trong những instantiation khác. Đặc biệt, các kiểu và biểu thức có thể phụ thuộc vào các kiểu tham số mẫu kiểu và các giá trị của các tham số mẫu không kiểu.

Từ khóa typename được sử dụng để thông báo cho trình biên dịch rằng biểu tượng bạn đang truy cập thực sự là loại bí danh/loại.

+1

Tôi tiếp tục ngạc nhiên trước phông chữ của sự khôn ngoan ở ngoài kia. Cảm ơn bạn. – StoneThrow

+0

Thành thật mà nói, lời giải thích tại liên kết mà bạn ghi chú đã đi trên đầu tôi. Nếu bạn rất quen thuộc với kịch bản này, bạn có thể giải thích nó theo các thuật ngữ đơn giản hơn không? Khi bạn nói "Từ khóa tên tệp được sử dụng để báo cho trình biên dịch biết rằng biểu tượng bạn đang truy cập thực sự là một loại bí danh/kiểu", "biểu tượng" trong ngữ cảnh này là gì? Lớp bên trong? Dựa trên phân tích cú pháp của tôi về giải thích, tôi không rõ tại sao giải pháp này là cần thiết cho tình huống này (các lớp bên trong), nhưng không bắt buộc với các lớp "không bên trong". Đánh giá cao nếu bạn có một lời giải thích sâu hơn, nhưng không phải lo lắng nếu không. Cảm ơn bạn. – StoneThrow

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