Как я избегаю коллизии имени с макросами, определенными в заголовочных файлах Windows?

У меня есть некоторый код C++, который включает названный метод CreateDirectory(). Ранее код только использовал STL и Повышение, но я недавно должен был включать <windows.h> таким образом, я мог поиск CSIDL_LOCAL_APPDATA.

Теперь, этот код:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

Больше компиляции:

error C2039: 'CreateDirectoryA' : is not a member of ...

Который соответствует этому макросу в winbase.h:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

Препроцессор переопределяет мой вызов метода. Там какой-либо возможный путь состоит в том, чтобы избежать этой коллизии именования? Или сделайте я должен переименовать мой CreateDirectory() метод?

17
задан Mike Willekes 23 February 2010 в 21:07
поделиться

5 ответов

Вам будет лучше, если вы просто переименуете свой метод CreateDirectory. Если вам нужно использовать API Windows, борьба с Windows.h - проигрышная битва.

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

14
ответ дан 30 November 2019 в 12:13
поделиться

Попробуйте использовать этот код:

$('#c').val("325");
-121--4213359-

Некоторые улучшения ответа Уильяма:

git config --global alias.tags 'log -n1 --pretty=format:%h%d'

выходные данные выглядят следующим образом:

~$ git tags
7e5eb8f (HEAD, origin/next, origin/master, origin/HEAD, master)
~$ git tags HEAD~6
e923eae (tag: v1.7.0)
-121--1081878-

Как разработчик, работающий на базе межплатформенных кодов, это проблема. Единственный способ справиться с этим -

  • убедиться, что windows.h - на Windows строит по крайней мере - универсально включен. Затем макрос CreateDirectory определяется в каждой из единиц компиляции и повсеместно заменяется на CreateStartW. Предварительно скомпилированные заголовки идеально подходят для этого

ИЛИ, если это неприятное предложение, (и это для меня)

  • изолировать использование windows.h в специальные служебные файлы Windows. Создание файлов, экспортирующих основные необходимые функциональные возможности. Заголовочные файлы должны использовать типы данных, совместимые с, но НЕ зависящие от включения windows.h. Файл реализации cpp должен (очевидно) использовать windows.h.

Если функции utlility должны включать файлы заголовков проекта с конфликтующими символами, то необходим следующий шаблон:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

Затем необходимо явным образом вызвать не макро-версию любых функций API Windows, которые у вас есть # undef 'd - CreateStartA или W и т.д.

2
ответ дан 30 November 2019 в 12:13
поделиться

Попробуйте marginTop вместо margin-top , например:

$("#ActionBox").css("marginTop", foo);
-121--3499327-

Из perlfaq5 :

Основная идея вставки, изменения или удаления строки из текстового файла включает чтение и печать файла в точку, который вы хотите сделать Perl не предоставляет произвольного доступа к строкам (тем более, что входной разделитель записей, $/, является изменяемым), хотя такие модули, как Tie:: File , могут его подделывать.

Программа Perl для выполнения этих задач принимает основную форму открытия файла, печати его строк, а затем закрытия файла:

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

while( <$in> )
    {
    print $out $_;
    }

close $out;

В этой основной форме добавьте части, которые необходимо вставить, изменить или удалить строки.

Чтобы добавить строки к началу, напечатайте эти строки перед вводом цикла, который печатает существующие строки.

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC

while( <$in> )
    {
    print $out $_;
    }

close $out;

Чтобы изменить существующие строки, вставьте код для изменения строк в цикле во время . В этом случае код находит все строчные версии «perl» и увеличивает их. Это случается для каждой линии, так что будьте уверены, что вы должны делать это на каждой линии!

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n";

while( <$in> )
    {
    s/\b(perl)\b/Perl/g;
    print $out $_;
    }

close $out;

Для изменения только определенной строки номер входной строки $. , является полезным. Сначала прочтите и распечатайте строки до строки, которую требуется изменить. Затем прочтите одну строку, которую требуется изменить, измените ее и распечатайте. После этого прочтите остальные строки и распечатайте их:

while( <$in> )   # print the lines before the change
    {
    print $out $_;
    last if $. == 4; # line number before change
    }

my $line = <$in>;
$line =~ s/\b(perl)\b/Perl/g;
print $out $line;

while( <$in> )   # print the rest of the lines
    {
    print $out $_;
    }

Чтобы пропустить строки, используйте элементы управления закольцовыванием. Следующий в этом примере пропускает строки комментариев, а последний останавливает всю обработку, как только он сталкивается с __ END __ или __ DATA __ .

while( <$in> )
    {
    next if /^\s+#/;             # skip comment lines
    last if /^__(END|DATA)__$/;  # stop at end of code marker
    print $out $_;
    }

Удалите ту же самую строку с помощью next , чтобы пропустить строки, которые не требуется отображать в выходных данных. Этот пример пропускает каждую пятую строку:

while( <$in> )
    {
    next unless $. % 5;
    print $out $_;
    }

Если по какой-то странной причине вы действительно хотите увидеть весь файл сразу, а не обрабатывать его построчно, вы можете поместить его в (если вы можете уместить всю вещь в памяти!):

open my $in,  '<',  $file      or die "Can't read old file: $!"
open my $out, '>', "$file.new" or die "Can't write new file: $!";

my @lines = do { local $/; <$in> }; # slurp!

    # do your magic here

print $out @lines;

Модули, такие как File:: Slups и Tie:: File могут помочь и с этим. Однако, если вы можете избежать одновременного чтения всего файла. Perl не отдаст эту память операционной системе, пока процесс не завершится.

Вы также можете использовать Perl one-liners для изменения файла на месте. В результате в inFile.txt файл заменяется новым содержимым. С помощью переключателя -p Perl оборачивает , в то время как закольцовывает код, указанный с помощью команды -e , и -i включает контекстное редактирование. Текущая строка в $ _ . При использовании -p Perl автоматически печатает значение $ _ в конце цикла. Для получения дополнительной информации см. perlrun .

perl -pi -e 's/Fred/Barney/' inFile.txt

Для создания резервной копии inFile.txt введите -i Расширение файла для добавления:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt

Чтобы изменить только пятую строку, можно добавить тестовую проверку $. , номер входной линии, затем выполните операцию только при прохождении теста:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt

Чтобы добавить строки перед определенной строкой, можно добавить строку (или строки!) до печати Perl $ _ :

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt

Можно даже добавить строку в начало файла, поскольку текущая строка печатается в конце цикла:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt

Для вставки строки после строки в файле используйте переключатель -n . Это просто как -p за исключением того, что он не печатает $ _ в конце цикла, поэтому вы должны сделать это сами. В этом случае сначала напечатайте $ _ , затем напечатайте строку, которую требуется добавить.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt

Для удаления строк напечатайте только те строки, которые требуется.

perl -ni -e 'print unless /d/' inFile.txt

    ... or ...

perl -pi -e 'next unless /d/' inFile.txt
-121--3147182-
#pragma push_macro("CreateDirectory")

Если ничего не работает, вместо переименования можно использовать собственное пространство имен для своих функций.

-2
ответ дан 30 November 2019 в 12:13
поделиться

Вы можете создать модуль, единственная цель которого - #include и поиск CSIDL_LOCAL_APPDATA, заключенного в функцию.

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}

кстати, молодцы, разобрались, что случилось!

10
ответ дан 30 November 2019 в 12:13
поделиться

#undef CreateDirectory

8
ответ дан 30 November 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: