У меня есть этот класс, который я только что написал, см. ниже. Я пытаюсь создать утилиту class для проверки аргументов командной строки в параметрах argc и argvmain().
class ArgumentGuard {
public:
ArgumentGuard() = default;
ArgumentGuard(int& argc, char const *argv[]) : _arc{argc}, _args{*argv} {}
bool has_arguments() const {
return _arc < 2 ? false : true;
}
private:
int _arc;
const char* _args[];
};
Использование:
int main(int argc, char const *argv[]) {
ArgumentGuard guard(argc, argv);
Ошибка:
In constructor 'ArgumentGuard::ArgumentGuard(int&, const char**)':
error: initializer for flexible array member 'const char* ArgumentGuard::_args []'
60 | ArgumentGuard(int& argc, char const *argv[]) : _arc{argc}, _args{*argv} {}
| ^~~~~~~~~~~~~~~~~~~
In file included from sectra.cpp:1:
In constructor 'ArgumentGuard::ArgumentGuard(int&, const char**)':
error: initializer for flexible array member 'const char* ArgumentGuard::_args []'
60 | SectraArgumentGuard(int& argc, char const *argv[]) : _arc{argc}, _args{*argv} {}
| ^~~~~~~~~~~~~~~~~~~
In constructor 'ArgumentGuard::ArgumentGuard(int&, const char**)':
error: initializer for flexible array member 'const char* ArgumentGuard::_args []'
60 | ArgumentGuard(int& argc, char const *argv[]) : _arc{argc}, _args{*argv} {}
| ^~~~~~~~~~~~~~~~~~~
const char* _args[] недействителен в С++. См. CASE 4 в ответе на странице Является ли int arr[ ] допустимым для C++?Гибкие члены массива не являются функцией C++, это расширение вашего компилятора. Если вам нужны ответы здесь, вам следует упомянуть компилятор и его версию. На данный момент дубликат верен, имея только тег c++, мы можем сделать вывод, что вы хотите написать код в соответствии со стандартом C++, если вы отредактируете вопрос, я смогу снять замыкание.
Хотя дубликат действительно объясняет ошибку, я не думаю, что он отражает то, что на самом деле пытался сделать этот спрашивающий. Измените const char* _args[]; на const char** _args; и измените _args{*argv} на _args{argv}.
@DrewDormann Им может понадобиться член гибкого массива, откуда вы знаете, что это не должно быть так?
Связанный материал: Допустимы ли члены гибкого массива в C++?
@Yksisarvinen Я основывал это предположение на том, что «я пытаюсь создать служебный класс для проверки аргументов командной строки в параметрах argc и argv функции main().». Это не похоже на работу с гибкими массивами.





Синтаксис массивов в стиле C может быть сложным.
Параметр функции, такой как ваш char const *argv[], на самом деле не является массивом — это сокращение указателя. Это то же самое, что char const **argv.
Измените свой класс, чтобы он также управлял указателем, а не массивом.
class ArgumentGuard {
public:
ArgumentGuard() = default;
ArgumentGuard(int argc, char const *argv[]) : _arc{argc}, _args(argv) {}
bool has_arguments() const {
return _arc < 2 ? false : true;
}
private:
int _arc;
const char** _args;
};
Кроме того, нет смысла передавать argc по ссылке только для того, чтобы скопировать его значение. Передайте его по значению, а не по ссылке.
Дрю, спасибо. Я решил использовать std::vector<T> ;-)
Помимо того, что VLA не является стандартным расширением, инкапсуляция ссылки (int&) внутри класса создает проблемы на протяжении всего срока службы, что приводит к зависанию. В общем, оба члена вашего ArgumentGuard неприятны.
Я приглашаю вас воспользоваться преимуществами современного C++ вместо того, чтобы пробовать сложные вещи и необработанные указатели. Аргументы командной строки — еще одно приложение для C++20 <ranges>:
#include <ranges>
int main(int argc, char const ** argv){
using namespace std::views; //counted, transform, as_const
auto args = counted(argv, std::size_t{argc})
| transform([](auto s){ return std::string_view{s}; })
| as_const;
auto args_guard = [args]
{ return std::ranges::size(args) >= 2; };
if (not args_guard())
return ~0;
//Blah blah
return 0;
};
В приведенном выше фрагменте args — это толстый указатель на аргументы командной строки, которые можно передавать по значению — если только не в отдельный поток. Он занимает мало памяти в автоматическом режиме и не вызывает динамического выделения. Каждый аргумент командной строки рассматривается как std::string_view. Таким образом, единственным случаем явного использования указателя теперь является неизбежная инициализация из argv.
Этот фрагмент обеспечивает большую безопасность при абсолютно нулевых затратах.
Это отличное и современное решение, хотя я не согласен с тем, что инициализация std::string_view из каждого const char* имеет «абсолютную нулевую стоимость». Это единственный код, который перебирает каждый символ.
Преобразование @DrewDormann в string_view — единственный вариант, который предотвращает использование необработанных строковых указателей. Затраты на вычисление длины компенсируются, когда объект string_view используется в выражении. Обычно он объединяется внутри функции форматирования.
Более того, преобразование происходит только при доступе к элементам. Поэтому я делаю ставку на его производительность по сравнению с любым другим конкурентом.
Кстати:
return _arc < 2 ? false : true;— это запутанный способ написанияreturn _arc >= 2;.