Для Windows popen
также работает, но открывается окно консоли, которое быстро мигает над вашим пользовательским интерфейсом. Если вы хотите быть профессионалом, лучше отключить этот «мигающий» (особенно если конечный пользователь может его отменить).
Итак, вот моя собственная версия для Windows:
(Этот код частично рекомбинирован из идей, написанных в образцах кодекса и MSDN)
//
// Execute a command and get the results. (Only standard output)
//
CStringA ExecCmd(
const wchar_t* cmd // [in] command to execute
)
{
CStringA strResult;
HANDLE hPipeRead, hPipeWrite;
SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
saAttr.bInheritHandle = TRUE; //Pipe handles are inherited by child process.
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe to get results from child's stdout.
if ( !CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0) )
return strResult;
STARTUPINFO si = { sizeof(STARTUPINFO) };
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdOutput = hPipeWrite;
si.hStdError = hPipeWrite;
si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.
PROCESS_INFORMATION pi = { 0 };
BOOL fSuccess = CreateProcessW( NULL, (LPWSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (! fSuccess)
{
CloseHandle( hPipeWrite );
CloseHandle( hPipeRead );
return strResult;
}
bool bProcessEnded = false;
for (; !bProcessEnded ;)
{
// Give some timeslice (50ms), so we won't waste 100% cpu.
bProcessEnded = WaitForSingleObject( pi.hProcess, 50) == WAIT_OBJECT_0;
// Even if process exited - we continue reading, if there is some data available over pipe.
for (;;)
{
char buf[1024];
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // no data available, return
break;
if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
// error, the child process might ended
break;
buf[dwRead] = 0;
strResult += buf;
}
} //for
CloseHandle( hPipeWrite );
CloseHandle( hPipeRead );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return strResult;
} //ExecCmd
Да, он плохо сформирован. Вот почему:
Функция constexpr
должна быть определена (не просто объявлена) перед использованием в постоянном выражении.
Итак, например:
constexpr int f(); // declare f
constexpr int x = f(); // use f - ILLEGAL, f not defined
constexpr int f() { return 5; } // define f, too late
Определения функций внутри спецификатора класса (а также инициализаторы и параметры по умолчанию) по существу разбираются в порядке, таком как они были определены вне класса.
Итак, это:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
Анализируется в следующем порядке:
struct X {
constexpr inline static int size(); // function body defered
static const int array[size()]; // <--- POINT A
};
constexpr inline int X::size() { return 5; }
То есть разбор тел функций откладывается до тех пор, пока не будет указан спецификатор класса.
Цель этой отсрочки разбора тела функции так что тела функций могут перенаправлять ссылочные классы, еще не объявленные в этой точке, а также поэтому они могут использовать свой собственный класс как полный тип:
struct X
{
void f() { T t; /* OK */ }
typedef int T;
};
По сравнению с областью пространства имен:
void f() { T t; /* error, T not declared */ }
typedef int T;
На POINT A
компилятор еще не имеет определения size()
, поэтому он не может его вызвать. Для производительности компиляции constexpr
функции должны быть определены перед их использованием в блоке трансляции перед вызовом во время компиляции, иначе компилятор должен будет сделать несколько проходов только для «ссылки» постоянных выражений для оценки.
По-видимому, это даже не ошибка , потому что его статус RESOLVED INVALID
, что означает, что люди, стоящие за GCC, и эта bugzilla, после рассмотрения проблемы, не думают, что это GCC bug.
Я напоминаю вам эту страницу, потому что есть ответ на это поведение в одном из связанных сообщений.
constexpr
в постоянном выражении, она должна быть определена (не просто объявлена) выше ее использования в блоке перевода.
– Andrew Tomazos
11 May 2013 в 06:01
constexpr
может использоваться, когда статический член данных constexpr
может.
– Ben Voigt
11 May 2013 в 06:41
static
. Если он определен как упомянутый в моем коде, тогда разрешите его использовать, иначе укажите ошибку. – iammilind 11 May 2013 в 13:23