2016-02-11 2 views
1

Предположим, у меня есть несколько файлов, которые все одинаково названы: Foo1Bar.h, Foo2Bar.h, Foo3Bar.h и т. Д. И т. Д. Теперь я хочу автоматически включить те, которые находятся в некотором main.c, в стиле «плагина», то есть , Я не хочу вспоминать до #include каждый. Можно ли это сделать с помощью токена? До сих пор, у меня есть:.Могу ли я использовать token-вставку и/или строку для #includes?

// this is the only line I want to have to change if I add Foo4Bar.h 
#define FOR_EACH_FOOBAR(T) T(1)T(2)T(3) 
//... somewhere else in my code 
#define RUN_SOME_FUNC(T) Foo##T##Bar().run(); 

И выше работает отлично (при условии, конечно, все мои Foo*Bar.h файлы имеют классы Foo*Bar с run() методом открытой (В случае, если это не ясно, мой пример здесь C++, но я не думаю, что сам вопрос, с #include, является C++ специфический).

Что у меня возникают проблемы дразнить из, если я могу сделать это с моими #include заявления, а также. Вместо

#include <Foo1Bar.h> 
#include <Foo2Bar.h> 
#include <Foo3Bar.h> 
#include <Foo4Bar.h> 

, было бы лучше (для меня), чтобы изменить что-то вроде:

FOR_EACH_FOOBAR(T) T(1)T(2)T(3)T(4) 
FOR_EACH_FOOBAR(INCLUDE) 

Я попытался:

#define INCLUDE(T) #include <Foo##T##Bar.h> 

но получаю ошибку: '#' is not followed by a macro parameter, потому что он пытается stringize начальный участок. Любая свертка или gyration, которые я пробовал, привела к той же (или подобной) ошибке, и я не могу понять, как либо избежать #include, либо как-то, чтобы заставить это работать.

Возможно ли, и если да, то как? Если нет, есть ли точная причина, почему нет?

+0

Я знаю этот момент, я тоже был там. Вот когда хочется иметь макросы, подобные Lisp :) Я предполагаю, что вместо того, чтобы пытаться сделать это «в», ваши исходные файлы добавляют шаг к вашему процессу сборки, чтобы создать заголовок «AllFooBars.h» со всеми этими включениями. –

+0

@ DanielJour О, хорошо, я не думал ни о чем вне исходных файлов, но это звучит разумно. Спасибо за эту мысль - независимо от того, возможно ли это сделать на C, сборка, вероятно, путь. – dwanderson

+0

Суть заключается в следующем: вы не можете использовать расширение макропроцессора для генерации препроцессорных директив. Таким образом, вам не разрешено создавать директивы '# include'. С '# include', это нормально, чтобы указать имя файла через макрос, но это все, что вы можете сделать. – AnT

ответ

1

Не совсем то, что вы хотите, потому что # команды обрабатываются препроцессором и это не выглядит слишком ли другой # команды результаты от расширения, но есть некоторая функциональность для «генерации» #include линий, они просто приходят после самого текста #include ...

https://gcc.gnu.org/onlinedocs/cpp/Computed-Includes.html

Искать здесь «#include anything else»: https://www.slac.stanford.edu/comp/unix/gnu-info/cpp_1.html

+1

Примечательной звездочкой является то, что Microsoft имеет расширение, позволяющее выпустить '# pragma' в результате расширения макроса, но это не имеет ничего общего с OP. –

+1

Часть: «это не выглядит, если другая команда' # 'возникает из-за расширения» - это ответ, который я искал (хотя и не надеялся), что объясняет, ПОЧЕМУ не существует никакого возможного способа получить '#define FOR_EACH ...' когда-либо работать для '# include' (это нормально, по крайней мере теперь я знаю). – dwanderson

1

Вы не можете использовать:

#define INCLUDE(T) #include Foo##T##Bar.h 

поскольку # используется в качестве оператора stringify аргумент.

#define STR(x) #x 

char const* s = STR(THIS); 

такая же, как с помощью:

char const* s = "THIS"; 

Учитывая, что

#define INCLUDE(T) #include Foo##T##Bar.h 

страдает от проблемы, что include не является одним из параметров макроса. Следовательно, использование #include не является законным.

Update

Я не думаю, что стандартная функциональность C препроцессор может быть использован для достижения того, что вы хотите достичь.Лично я предпочел бы видеть

#include <Foo1Bar.h> 
#include <Foo2Bar.h> 
#include <Foo3Bar.h> 
#include <Foo4Bar.h> 

в моем файле, чем

FOR_EACH_FOOBAR(T) T(1)T(2)T(3)T(4) 
FOR_EACH_FOOBAR(INCLUDE) 
+0

Правильно, я знал об этом, основываясь на ошибке, которую я получил при попытке скомпилировать. Мой вопрос: есть ли способ? Я не очень хорошо знаком/леденец с вставкой и скручиванием токенов, поэтому мне интересно, нужна ли мне еще более умная работа. – dwanderson

+0

@dwanderson, можете ли вы добавить к своему сообщению несколько строк, показывающих, как вы хотите использовать этот макрос, и как это упростит вашу жизнь, когда вы добавите Foo4Bar.h? –

+0

Я согласен с указанным примером. С другой стороны, я бы скорее увидел нечто вроде '#include QLIB_HEADERS (" qlib.h ")' than '#include" ../../ qlib/headers/qlib.h "или' #include " qlib.h "// Надеюсь, что путь включения может найти правильную вещь". – supercat