Я реализовал getop()
в C ++ .Это класс со всеми видами звонков и свистков.
Один из этих звонков был бы способом проверки того, что пользователь вводит допустимые параметры во время компиляции.У меня уже есть часть этого для флагов (не показанных здесь), но я пытался заставить это работать для struct option
, и в настоящее время у меня не было большого успеха.
Прежде всего, код позволяет мне определить массив опций, используя функцию define_option()
.Я хочу иметь возможность указывать поля структуры параметров в любом порядке и иметь некоторые проверки их работоспособности.Поэтому я использую список аргументов для шаблонной функции.Каждый аргумент является классом, который создается на месте, а затем define_option()
выбирает правильный класс для каждого поля, извлекая значение.
Здесь все работает как шарм.Довольно простой C ++.
Проблема, с которой я сталкиваюсь, находится внутри класса define_option()
.Скажем, например, что я должен был попробовать следующее:
... define_option(...)
{
...
option opt = { ... };
static_assert(opt.f_short_name != '\0', "this failed");
...
}
Здесь я получаю ошибку.static_assert()
говорит мне, что opt
не является константой.
a.cpp: 168: 1: ошибка: непостоянное условие для статического утверждения
Итакмой шаг - пометить переменную opt
как constexpr
(что-то, что говорит ошибка, чтобы решить static_assert()
.)
... define_option(...)
{
...
constexpr option opt = { ... };
...
}
Теперь, даже без static_assert()
, код не 'т компилировать.Я получаю следующую ошибку:
a.cpp: 168: 5: ошибка: 'args # 0' не является константным выражением
Я думаю, что этона самом деле не выполнимо из функции define_option()
, хотя можно проверить итоговый список опций, как показано в рабочем примере ниже.Таким образом, в итоге глобальная переменная opt
является статической, полностью определенной во время компиляции (нет кода, необходимого для повторной работы над таблицей во время выполнения), но это не помогает мне, так как я не могу убедиться, что аргументы длякаждый вариант будет работать, как и ожидалось.
У меня есть онлайн-запущенный образец на колиру.
// compiled with: g++ -std=c++14 -o a ~/tmp/a.cpp
//
#include <iostream>
typedef char32_t short_name_t;
constexpr short_name_t NO_SHORT_NAME = L'\0';
struct option
{
short_name_t f_short_name = NO_SHORT_NAME;
char const * f_name = nullptr;
};
template<typename T, T default_value>
class OptionValue
{
public:
typedef T value_t;
constexpr OptionValue<T, default_value>()
: f_value(default_value)
{
}
constexpr OptionValue<T, default_value>(T const v)
: f_value(v)
{
}
constexpr value_t get() const
{
return f_value;
}
private:
value_t f_value;
};
class ShortName
: public OptionValue<short_name_t, NO_SHORT_NAME>
{
public:
constexpr ShortName()
: OptionValue<short_name_t, NO_SHORT_NAME>()
{
}
constexpr ShortName(short_name_t name)
: OptionValue<short_name_t, NO_SHORT_NAME>(name)
{
}
};
class Name
: public OptionValue<char const *, nullptr>
{
public:
constexpr Name()
: OptionValue<char const *, nullptr>()
{
}
constexpr Name(char const * name)
: OptionValue<char const *, nullptr>(name)
{
}
};
template<typename T, typename F, class ...ARGS>
constexpr typename std::enable_if<std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
{
return first.get();
}
template<typename T, typename F, class ...ARGS>
constexpr typename std::enable_if<!std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
{
return find_option<T>(args...);
}
template<class ...ARGS>
constexpr option define_option(ARGS ...args)
{
option opt =
{
.f_short_name = find_option<ShortName >(args..., ShortName()),
.f_name = find_option<Name >(args...),
};
return opt;
}
constexpr option const opt[] =
{
define_option(
Name("--help"),
ShortName('h')
)
};
// this test works as expected here
// but it does not work from inside define_option()
//
static_assert(opt[0].f_name[0] != '-', "Wrong start?!");
int main(int argc, char * argv [])
{
std::cerr << "opt[0].f_short_name = " << opt[0].f_short_name << std::endl;
return 0;
}
В настоящее время я ограничен C ++ 14.Если есть решение C ++ 17, мне все равно будет интересно.