Немного фона: я хочу написать инструмент, который компилирует кучу названных вещей в код на С++. Список меняется, и я не хочу восстанавливать мир, когда это произойдет. Несмотря на это, я хочу обратиться к скомпилированному коду с помощью (буквального) имени.
В качестве примера чего-то, что не совсем правильно, я мог бы поместить это в заголовок:
template<int name> void func();
Затем мой инструмент может генерировать код, например:
template<> void func<1>() { ... }
template<> void func<2>() { ... }
template<> void func<3>() { ... }
Теперь я могу называть их "именем" в любом месте без предварительного объявления каждого из них.
Я хочу сделать это, но с чем-то более описательным, чем целыми. В идеале я хочу текст какой-то формы. Мне нужно что-то вроде:
#define FUNC_WITH_NAME(name) func_named_ ## name
Это не работает, хотя: ему требуется объявление func_named_whatever.
Следующая попытка тоже не подходит (и она специфична для GCC):
#define FUNC_WITH_NAME(name) ({extern void func_named_ ## name; func_named_ ## name;})
Он терпит неудачу, потому что, если он используется внутри пространства имен, он в конечном итоге ищет func_named_whatever в этом пространстве имен.
Самое лучшее, что я придумал, это:
template<char... tagchars> int tagged();
namespace NS {
int caller()
{
return tagged<'n', 'a', 'm', 'e'>();
}
}
Это работает, но это уродливо (и не очевидно, как превратить строковый литерал в пакет параметров, не перепрыгивая через неприятные обручи). Кроме того, если символ не разрешает, то сообщение об ошибке из g++ ужасно:
In function `NS::caller()':
named_symbol.cpp:(.text+0x5): undefined reference to `int tagged<(char)110, (char)97, (char)109, (char)101>()'
collect2: error: ld returned 1 exit status
Единственное, что я придумал, это расширение gcc:
extern void func_named_whatever __asm__("func_named_whatever");
Но это не так хорошо, как аргумент шаблона (он влияет только на вызовы этой функции, он не влияет на использование магических asm -сертифицированных символов, когда они являются аргументами шаблона), и он побеждает любая проверка времени соединения, поскольку она отключает манипуляцию.