2013-12-02 6 views
8

Интересно, как определить макрос, который для данного имени класса выводит его пространство имен и имя класса в формате, например: «Namespace.SubNamespace.ClassName»?Возможно ли получить строку, содержащую пространство имен и имя класса во время компиляции?

Так сочинительство что-то вроде этого:

// MyClass.h 
#include <string> 

namespace NS { 
namespace SNS { 
    class MyClass { 
    static std::string str; 
    }; 
} 
} 

//MyClass.cpp 
#include <MyClass.h> 
using namespace std; 
string NS::SNS::MyClass::str = SUPER_MACRO(/*params if needed yet none would be prefered*/); 

Я хочу, чтобы ул быть "NS.SNS.MyClass". Мне бы очень хотелось, чтобы макрос имел, по возможности, параметры профиля (что означает один или ничего).

альтернативы Интересно, если такая вещь может быть сделано с помощью шаблонов с чем-то вроде:

string NS::SNS::MyClass::str = GetTypeNameFormater<NS::SNS::MyClass>(); 

Как сделать такую ​​вещь (с использованием форсирования, СТЛ и имеющий только C++ 03 под рукой)?

+0

Очевидно, это не макрос. Пространства имен требуют синтаксического анализа, а препроцессор (который обрабатывает макросы) работает до разбора. '__func__' - не настоящий макрос, несмотря на его внешний вид. – MSalters

ответ

3

Нет стандартного способа сделать это. Единственным стандартным макросом, предоставленным для предоставления информации о области, является макрос C99 __func__.

Что вы можете сделать, это получить имя символа через std::typeinfo, а затем бросить его в конкретный API-интерфейс для компиляции и затем проанализировать пространство имен.

http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html дает примеры того, как это сделать. Это должно работать с clang и OS X.

В качестве альтернативы вы можете написать набор макросов для определения пространств имен и соответствующей статической строки, а затем взломать ваши строки вместе.

Ни один вариант не будет особенно красивым.

+0

-1 ['std :: type_info :: name'] (http://en.cppreference.com/w/cpp/types/type_info/name) не требуется содержать пространство имен. На самом деле, не требуется никаких ограничений, и реализация, которая всегда возвращает 'X' для любого типа, является совместимой. – IInspectable

+0

@IInspectable Вот почему я упомянул специфические для компилятора API. Я полностью понимаю, что для этого нет прямого подхода, совместимого со стандартами, но вы можете сделать это на определенных компиляторах. Это намного лучше, чем ничего, и работает, по крайней мере, на двух основных компиляторах. – pmr

1

Это не подход, основанный на компиляции, но он может дать вам то, что вы хотите.

Вы можете попробовать что-то вроде:

nm ./a.out | grep "ZN" | c++filt 

Похоронен на выходе я вижу:

NS::SNS::MyClass::str 

Вы также можете использовать demangle.h, хотя я не знаю, как вы бы получим искаженное имя (typeid не дает мне многого.)

Вы также можете рассмотреть возможность использования Boost Reflect, Boost Typetraits, Reflex или clang. Возможно, вы сможете сделать какое-то отражение, используя API-интерфейс clang.

Смежные вопросы