2010-02-16 20 views
5

Điều này chỉ cần làm việc trong g ++.C++ mẫu ma thuật đen

Tôi muốn có một chức năng

template<typename T> std::string magic(); 

ví dụ rằng:

Class Foo{}; magic<Foo>(); // returns "Foo"; 
Class Bar{}; magic<Bar>(); // returns "Bar"; 

Tôi không muốn điều này được thực hiện thông qua chuyên môn hóa (tức là phải xác định ma thuật đối với từng loại tôi hy vọng. để kéo một số ma thuật vĩ mô/mẫu màu đen ở đây. Bất cứ ai cũng biết làm thế nào?)

Cảm ơn!

+1

Bây giờ phần nào cần thiết và bạn đang viết phần nào vì bạn nghĩ nó cần thiết. Lớp Foo có quan trọng không? Hãy cho chúng tôi một trường hợp sử dụng thực tế hơn. –

+1

Một yêu cầu khá rõ ràng của nó đối với một số loại cơ chế phản xạ tĩnh đơn giản, không mang lại đầy đủ gamut của RTTI. – Justicle

+0

Tôi muốn có một chức năng mà tôi có thể vượt qua bất kỳ loại nào và nó sẽ trả lại cho tôi tên của loại đó. – anon

Trả lời

7

Hãy thử typeid(Foo).name() cho một sự khởi đầu. Phân tích cú pháp khi bạn thấy phù hợp; sẽ được thực hiện phụ thuộc (nhưng chỉ đơn giản là nhận được một chuỗi trở lại là xách tay).

+0

typeid (Foo) .name() sẽ trả về một tên bị cắt xén. (ví dụ 3Foo) –

+1

Phân tích cú pháp như bạn thấy phù hợp, ví dụ: 'char * n = typeid (Foo) .name(); trong khi (* n && * n <'A') ++ n; ' – Potatoswatter

4

Nhà điều hành stringizing trên macro có thể là những gì bạn đang tìm kiếm:

#define MAGICCLASSNAME(str) std::string magic(#str) 
class Foo{}; MAGICCLASSNAME(foo) 
1

tôi đã đưa ra dưới đây:

#include <iostream> 
#include <string> 
#include <typeinfo> 

using namespace std; 
class Foo{}; 
class Bar{}; 

template<typename T> 
inline std::string magic(const T& obj) 
{ 
return typeid(obj).name(); 
} 

int main() 
{ 
Foo a; 
cout << magic<Foo>(a); // returns "Foo"; 
} 

Tôi thử nghiệm này với g ++ và hoạt động tốt.

Ngoài ra tôi đã nhận nó từ this SO câu trả lời.

10

Để chuyển đổi loại (hoặc số nhận dạng khác) thành chuỗi, bạn cần macro, nhưng macro không thể kiểm tra xem tham số của nó có phải là loại hợp lệ hay không. Để thêm loại kiểm tra một hàm template có thể được thêm vào macro:

template<typename T> 
std::string magic_impl(const char *name) { return name; } 

#define more_magic(a) magic_impl<a>(#a) 
#define magic(a) more_magic(a) 

Đây magic(int) cho chuỗi "int" khi magic(Foo) đưa ra một "‘Foo’đã không tuyên bố" lỗi nếu không có lớp như vậy.

+0

Trong tất cả các câu trả lời được đưa ra ở đây, tôi thích câu trả lời này là tốt nhất vì a) Nó đánh máy b) Kết quả là tên lớp và không phải bất kỳ hình thức nào có thể phụ thuộc vào trình biên dịch. – ardsrk

+0

Tôi vẫn không hiểu mục đích của 'more_magic' ... –

+1

more_magic tồn tại chỉ để kiểm tra xem loại có tên" a "được khai báo và nằm trong phạm vi không. Không có điều đó tôi có thể gọi phép thuật (%%%%) và nhận cuộc gọi thành công mặc dù %%%% không thể là tên hợp pháp cho một loại. – ardsrk

-1

Trong C++ có thể bạn đang tìm kiếm mẫu ma thuật đen. Nếu vậy, Modern C++ Design sẽ hữu ích.

+0

-1 Không phải là rất hữu ích cũng không liên quan đến câu hỏi – Tomas

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