2016-01-27 17 views
17

Có cách nào để xây dựng một typedef bên trong một kiểu khai báo cho loại được tuyên bố (xung quanh) chính nó mà không nêu tên của loại?Typedef để loại xung quanh trong C++

Ví dụ:

class X 
{ 
    public: 
    typedef <fill in magic here> MyType; 
    //... 
}; 

Bối cảnh: Điều này có vẻ ngớ ngẩn trên cái nhìn đầu tiên. Tôi cần điều này bởi vì tôi xây dựng biên dịch thời gian phản ánh của các lớp dữ liệu của tôi bằng cách sử dụng macro. Vì vậy, có một macro được chèn vào khai báo của lớp dữ liệu cần xử lý với kiểu mà nó được chèn vào. Cho đến nay tôi đã tìm ra giải pháp làm việc cho MSVC và g ++, cả hai đều dựa vào những gì tôi nghĩ là những sai sót trong quá trình thực hiện. Vì vậy, họ có thể không hoạt động trên một phiên bản mới hơn. Clang không "ăn" một trong các giải pháp này.

Giải pháp hiện tại của tôi cho MSVC định nghĩa một phương thức và sau đó lấy địa chỉ của nó chỉ bằng tên của nó và gọi một trình trợ giúp nhỏ "trả về" loại của lớp đó. (Clang và g ++ mong đợi tên đầy đủ của phương thức bao gồm tên lớp của nó).

Giải pháp hiện tại của tôi cho g ++ xác định phương pháp tĩnh với kiểu trả về std::remove_reference(decltype(*this)). (Clang và MSVC không cho phép this trong ngữ cảnh tĩnh).

Tôi hoàn toàn sẽ thích giải pháp phù hợp tiêu chuẩn nhưng giải pháp đặc biệt cho tiếng kêu vang cũng sẽ ổn cho thời điểm này.

Nếu không có gì hoạt động, tôi phải chuyển tên của lớp sang macro nhưng tôi cố tránh điều này vì tôi đã có nhiều mã bằng cách sử dụng macro.

EDIT: Thêm một mẫu về cách thức phản ánh hoạt động (trong đó có thể làm rõ những gì tôi cần):

class X : public Y 
{ 
    public: 
    //.. constructor and such stuff... 

    int a; 
    double b; 
    std::string c; 

    CLASSHEAD(Y) 
     FIELD(a) 
     FIELD(b) 
     FIELD(c) 
    CLASSFOOT 
}; 

CLASSHEAD là macro mà cần xác định typedef. Nó là một macro VAR_ARGS trong đó các đối số nhận các lớp cơ sở. Như đã nói: Có thể đặt tên lớp là đối số đầu tiên (kết quả là CLASSHEAD(X, Y) trong ví dụ). Nhưng tôi gần như không thể tưởng tượng rằng không có giải pháp cho một nhiệm vụ "đơn giản" như đánh máy kiểu xung quanh ...

+0

Thực ra, không rõ lý do tại sao bạn không thể làm 'typedef X MyType;', và sau đó có các macro sử dụng 'MyType'? – BoBTFish

+0

Vì vậy, tất cả các lớp học dự kiến ​​sẽ sử dụng cơ chế này kế thừa từ cùng một cơ sở? (Trong trường hợp này tôi có thể khôi phục câu trả lời CRTP của mình). – BoBTFish

+1

Lý do duy nhất tôi có thể nghĩ là cần phải có chữ ký chức năng. Trong bản thân hàm, bạn sẽ sử dụng 'typedef std :: remove_reference (decltype (* this)) :: gõ MyType;' như trên. Bạn có thể tạo các mẫu hàm đó, sau đó 'static_assert (std :: is_same :: value);'. Không đẹp, không thể nghĩ ra bất cứ điều gì tốt hơn. – BoBTFish

Trả lời

-3

Nohting hoạt động để sử dụng tên lớp trong macro là giải pháp làm việc duy nhất

2

Điều này không đáp ứng chính xác đặc điểm của bạn, nhưng tôi nghĩ nó khá gần:

class X 
{ 
//Stuff... 

//Use Macros to add: 
struct MyType; 

//Use class closing macro to insert variable between class-ending brace and semicolon  


} TYPE_VAR; 
//Perhaps add random stuff to TYPE_VAR name to avoid collisions, like __FILE__ 
struct decltype(TYPE_VAR)::MyType 
{ 
    typedef decltype(TYPE_VAR) V; 
}; 

Sau đó truy cập vào loại X sử dụng

X::MyType::V 

Ví dụ, một CLASSFOOT đơn giản có thể trông như thế này:

#define CLASSFOOT /*Your classfoot here*/ } TYPE_VAR; struct decltype(TYPE_VAR)::MyType {typedef decltype(TYPE_VAR) V; 
//No }; at end on purpose- this will come from the class in which you placed CLASSFOOT 

Điều này có đủ tốt cho mục đích của bạn không?

+0

Phía bên trái là 'MyType :: V' không thể được sử dụng bên trong định nghĩa' X' (một tính năng mà tôi nghĩ OP cần) –

+1

Điều này không trả lời được câu hỏi gốc. – mmmmmmmm

0

Vì bạn đang sử dụng các macro, bạn có thể sử dụng giải pháp này https://stackoverflow.com/a/21143997/2173029

#define CLASS_WITH_MY_TYPE(ClassName) \ 
    class ClassName     \ 
    {         \ 
     using MyType = ClassName; 

Và sau đó sử dụng như

CLASS_WITH_MY_TYPE(X) 
public: 
    struct Y 
    { 
    using T = MyType; 
    }; 
}; 

static_assert(std::is_same<X, typename X::Y::T>::value, ""); 

đánh dấu như wiki cộng đồng kể từ @ Chris đề cập đến liên kết và câu trả lời ban đầu là đăng bởi @Bartek Banachewicz

+0

@ RüdigerStevens Tôi nghĩ bạn có nghĩa là macro 'CLASSHEAD'. – Rumburak

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