Не совсем то, что вы просили, но ... если вы проверяете дубликаты внутри checked_arr()
и вы бросаете исключение, если вы находите его, у вас есть исключение при выполнении checked_arr()
времени выполнения и ошибка компиляции при выполнении его компиляции-time.
Я имею в виду ... вы можете написать
template <std::size_t N0 = 0u, typename ... Ts,
std::size_t N = (N0 > sizeof...(Ts)) ? N0 : sizeof...(Ts)>
constexpr auto checked_arr (Ts ... args)
{
std::array<Arg_Opt_Tuple, N> arr {args...};
for ( auto i = 0u ; i < sizeof...(Ts) ; ++i )
for ( auto j = 0u; j < sizeof...(Ts) ; ++j )
if ( (i != j) && (arr[i].sc == arr[j].sc) )
throw std::runtime_error("equal sc");
return arr;
}
(не по теме: соблюдайте трюк с N0
и N
: так что вы должны явно N0
только когда больше sizeof...(Ts)
)
Если вы позвоните
constexpr auto opts = checked_arr(
Arg_Opt_Tuple{"hello", 'h', false},
Arg_Opt_Tuple{"world", 'g', true},
Arg_Opt_Tuple{"goodbye", 'h', false},
Arg_Opt_Tuple{"hello", 'r', false}
);
, вы получите ошибку компиляции;в g ++
prog.cc:26:42: error: expression '<throw-expression>' is not a constant expression
26 | throw std::runtime_error("equal sc");
| ^
Ниже приведен пример полной компиляции C ++ 17 (не компилируется, если вы помещаете коллизию в opts
)
#include <array>
#include <string>
#include <exception>
struct Arg_Opt_Tuple {
std::string_view mc{}; // multichar ie "help"
char sc{}; // singlechar ie 'h'
bool is_flag{};
};
template <std::size_t N0 = 0u, typename ... Ts,
std::size_t N = (N0 > sizeof...(Ts)) ? N0 : sizeof...(Ts)>
constexpr auto checked_arr (Ts ... args)
{
std::array<Arg_Opt_Tuple, N> arr {args...};
for ( auto i = 0u ; i < sizeof...(Ts) ; ++i )
for ( auto j = 0u; j < sizeof...(Ts) ; ++j )
if ( (i != j) && (arr[i].sc == arr[j].sc) )
throw std::runtime_error("equal sc");
return arr;
}
int main ()
{
constexpr auto opts = checked_arr(
Arg_Opt_Tuple{"hello", 'h', false},
Arg_Opt_Tuple{"world", 'g', true},
Arg_Opt_Tuple{"goodbye", 'i', false},
Arg_Opt_Tuple{"hello", 'r', false}
);
}
Но я предлагаю просто инициализироватьмассив как constexpr
переменная
constexpr std::array opts {
Arg_Opt_Tuple{"hello", 'h', false},
Arg_Opt_Tuple{"world", 'g', true},
Arg_Opt_Tuple{"goodbye", 'i', false},
Arg_Opt_Tuple{"hello", 'r', false}
};
и проверить его, вызывая функцию constexpr
внутри static_assert()
static_assert( checkOpts(opts) );
, где checOpts()
- это что-то вроде
template <std::size_t N>
constexpr bool checkOpts (std::array<Arg_Opt_Tuple, N> const & arr)
{
for ( auto i = 0u ; i < N ; ++i )
for ( auto j = 0u; j < N ; ++j )
if ( (i != j) && (arr[i].sc == arr[j].sc) )
return false;
return true;
}