2012-01-26 23 views
6

Trong số answer Tôi đưa ra, sử dụng this và thuộc tính của lớp _arg trong loại trả về theo sau là một phần của biểu thức decltype. Có thể làm mà không có, nhưng bất tiện.Sử dụng tính năng này và các thuộc tính trong các kiểu trả về của hàm thành viên?

Cả clang 3.0 (xem bên dưới) cũng không phải gcc 4.5.2 chấp nhận nó.

#include <iostream> 

class MyClass { 
public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 

private: 
    int _arg; 
}; 

struct Id { 
    template <typename V> 
    V operator()(V v) const { return v; } 
}; 

struct ComplexId { 
    template <typename C, typename V> 
    V operator()(C const&, V v) { return v + 1; } 
}; 

int main() { 
    Id id; ComplexId complex; 

    MyClass c(0); 

    std::cout << c.apply(id) << " " << c.apply(complex) << "\n"; 
} 

kêu vang 3.0 nói:

$ clang++ -std=c++11 -Weverything test.cpp 
test.cpp:8:38: error: use of undeclared identifier '_arg' 
     auto apply(F& f) -> decltype(f(_arg)) { 
            ^
test.cpp:8:45: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(_arg)) { 
              ^
test.cpp:8:45: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(_arg)) { 
          ~~~~~~~~  ^
test.cpp:8:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(_arg)) { 
    ^
test.cpp:13:39: error: invalid use of 'this' outside of a nonstatic member function 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
            ^
test.cpp:13:52: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
               ^
test.cpp:13:52: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
          ~~~~~~~~    ^
test.cpp:13:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
    ^
8 errors generated. 

Hum ... không tuyệt vời như vậy.

Tuy nhiên, hỗ trợ của C++ 11 là hacky tốt nhất trong hầu hết các trình biên dịch và tôi không thể tìm thấy hạn chế cụ thể được đề cập trong tiêu chuẩn (n3290).

Trong những ý kiến, Xéo gợi ý rằng nó có thể đã là một khiếm khuyết trong các tiêu chuẩn ...

Vì vậy, điều này có cho phép hay không?

Phần thưởng: và thực hiện các phiên bản mới hơn của hỗ trợ clang/gcc này?

+0

Clang 3.1 HEAD cũng có cùng lỗi. – Xeo

+0

Lỗi tương tự trên GCC 4.7. –

+0

Btw, tôi vừa tìm thấy [câu hỏi thú vị tương tự] này (http://stackoverflow.com/q/7255379/500104). Ngoài ra, với đề xuất của @Johannes tuyên bố thành viên trả trước, tôi chỉ nhận được một lỗi về 'this' theo kiểu trả về, không phải về' _arg' nữa với HEAD Clang 3.1. – Xeo

Trả lời

9

Tôi đã xác nhận sai. Đó là a defect at some point, nhưng cuối cùng là resolved and voted into the FDIS.

§5.1.1 [expr.prim.general]

Nếu một tuyên bố tuyên bố một hàm thành viên hoặc thành viên hàm mẫu của một lớp X, khái niệm this là một prvalue kiểu “con trỏ đến cv-vòng-seqX” giữa không bắt buộc cv-qualifer-seq và kết thúc của định nghĩa chức năng , thành viên khai báo hoặc người khai báo.

Như vậy, Clang và GCC chưa thực hiện chính xác.

struct X{ 
    // 'this' exists between the | markers 
    void f() const volatile | { 
    } | 
    auto g() const volatile | -> void { 
    } | 
}; 
1

Tôi không biết nếu những gì bạn viết là hợp pháp, nhưng có một số cách khác để đạt được những gì bạn muốn:

template <typename F> 
    auto apply(F& f) -> decltype(f(*(MyClass*)0, (int)0)) { 
    return f(*this, _arg); 
    } 

Hoặc:

template <typename F> 
    typename std::result_of<F(MyClass,int)>::type apply(F& f) { 
    return f(*this, _arg); 
    } 
+0

Trong câu trả lời tôi liên kết, một hình thức chi tiết hơn được đưa ra có hiệu quả. Lưu ý sự tồn tại của 'std :: declval ' được cho phép trong các ngữ cảnh không được đánh giá, con trỏ null là không cần thiết :) –

5

Mã của bạn không hợp lệ C++ 11, vì lớp không được xem xét hoàn chỉnh theo kiểu trả về của hàm thành viên. Bạn chỉ có thể truy cập các thành viên đã được khai báo trước đó. Giống như rất

class MyClass { 
private: 
    int _arg; 

public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 
}; 

Modulo rằng, có sử dụng this là hợp lệ trong C++ 11 trong một loại dấu sự trở lại.

+0

Ah, điều đó thật thú vị. Tôi đã không suy nghĩ về nó, nhưng nó có ý nghĩa kể từ khi, nếu tôi nhớ lại chính xác, cùng áp dụng cho các loại (tức là họ cần phải được khai báo trước khi sử dụng ngay cả trong các lớp học). –

+0

Không có bên trong cơ quan chức năng thành viên lớp học được coi là hoàn thành. do đó, ngay cả các loại thành viên được khai báo sau đó đều hiển thị. –

+0

Tôi đã suy nghĩ cụ thể về [this] (http://ideone.com/T1ZS8): 'struct A {type foo(); typedef int type; }; '. Luôn báo lỗi tôi là * phân tích cú pháp kiểu cũ *: x –

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