Некоторое время назад (при поиске в сети утилиты Identity<T>
) я попал на эту страницу .
Вкратце, чтобы ответить на вопрос, если у вас нет поддержки C ++ 11 и / или вы не можете (или не хотите) использовать typedef
, вы называете свой макрос «правильным» способ:
// If an argument contains commas, enclose it in parentheses:
SET_TYPE_NAME((std::map<int, int>), "TheMap")
// For an argument that doesn't contain commas, both should work:
SET_TYPE_NAME((SomeType1), "TheType1")
SET_TYPE_NAME(SomeType2, "TheType2")
, а затем , чтобы избавиться от (возможных) нежелательных скобок вокруг типа , вы можете использовать «помощник», подобный этому:
template<typename> struct RemoveBrackets;
template<typename T> struct RemoveBrackets<void (T)> {
typedef T Type;
};
и в вашем макросе измените строку:
std::string name<TYPE>() { \
до:
std::string name< RemoveBrackets<void (TYPE)>::Type >() { \
(или определить вспомогательный макрос, скажем
#define REMOVE_BRACKETS(x) RemoveBrackets<void (x)>::Type
затем замените строку на
std::string name< REMOVE_BRACKETS(TYPE) >() { \
).
(Для полной истории прочитайте параграф «Еще лучшее решение» в конце статьи, ссылки на которую приведены выше.)
Редактировать: только что нашел , что . Но он использует <void X>
, когда он действительно должен использовать <void (X)>
(в get_first_param<void X>::type
); действительно, скобки необходимы, если вы передаете «простой» аргумент без скобок (например, SomeType2
в моем коде выше) - и они не повредят, если X
уже заключен в скобки (например, , void ((SomeType1))
эквивалентно void (SomeType1)
, опять же, см. Статью). (Кстати, я заметил, что многие ответы на другой SO-странице, по сути, «Макросы тупые». Я не буду комментировать.)