2015-12-22 21 views
12

Trong bối cảnh của một ứng dụng C++ 14, tôi sử dụng một chương trình nào có thể được nối lại như sau (tối thiểu kiểm tra tái sản xuất):lỗi xác định một kiểu trả về chung trong C++ 11

template <class Container> 
struct LocateFunctions {  
    auto get_it() const // <-- here is the problem 
    { 
    auto ret = typename Container::Iterator(); 
    return ret; 
    } 
}; 

template <typename T> 
struct A : public LocateFunctions<A<T>> {  
    struct Iterator {}; 
}; 

int main() { 
    A<int> a; 
} 

Cách tiếp cận này biên dịch và chạy hoàn hảo trong C++ 14, với trình biên dịch GCC và Clang.

Bây giờ tôi muốn di chuyển ứng dụng của mình sang Windows và tôi đang sử dụng MinGW. Thật không may, phiên bản mới nhất của nó mang GCC 4.9 mà không biên dịch C++ 14. Điều đó dường như không phải là một vấn đề nghiêm trọng bởi vì tôi có thể viết lại các cấu trúc C++ 14 trong C++ 11. Vì vậy, tôi viết lại phương thức get_it() như sau:

typename Container::Iterator get_it() const 
{ 
    auto ret = typename Container::Iterator(); 
    return ret; 
} 

Thật không may nó không biên dịch. Cả hai trình biên dịch tạo ra các lỗi sau:

error: no type named ‘Iterator’ in ‘struct A<int>’ 
    typename Container::Iterator get_it() const 
          ^

Tôi cũng đã cố gắng:

auto get_it() const -> decltype(typename Container::Iterator()) 
{ 
    auto ret = typename Container::Iterator(); 
    return ret; 
} 

nhưng tôi nhận được chính xác những lỗi tương tự.

Vì hai trình biên dịch không nhận ra kiểu trả về, tôi cho rằng không thể xác định được. Nhưng tôi không thực sự biết tại sao.

Ai đó có thể giải thích cho tôi lý do tại sao không biên dịch và cuối cùng là một cách để tái cấu trúc trong C++ 11 biên dịch?

Trả lời

16

Bạn đang sử dụng CRTP; LocateFunctions được khởi tạo với chuyên môn chưa đầy đủ của A (A<int>), do đó truy cập vào các thành viên chuyên môn đó cung cấp thông báo lỗi khá sai lệch ("không ... được đặt tên ... trong ..." thay vì "... không đầy đủ"). Tuy nhiên, trong ví dụ của bạn chức năng temploid get_it chỉ là (nếu bao giờ) instantiated sau A<int> thực sự là định nghĩa, làm cho typename-specifier well-formed.

Để giải quyết sự cố này, hãy cố gắng đạt được hiệu ứng tương tự, ví dụ: qua số

template <typename T=Container> 
typename T::Iterator get_it() const 
{ 
    static_assert(std::is_same<T, Container>{}, "You ain't supposed to supply T!"); 
    auto ret = typename T::Iterator(); 
    return ret; 
} 

Demo bằng GCC 4.9.

+7

Temploid? Đó có phải là một từ không? – Quentin

+6

@Quentin Có. Nó biểu thị các thành viên mẫu không phải mẫu, bị ảnh hưởng bởi một DR nhất định đã mở 15 năm trước. – Columbo

+3

upvote cho temploid! – Barry

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