Skip to content

Commit 6872bcf

Browse files
committed
Add workaround for hang on clang
1 parent 5326868 commit 6872bcf

File tree

2 files changed

+45
-33
lines changed

2 files changed

+45
-33
lines changed

include/args.hpp

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,49 @@ template<class Range>
7171
using value_of = std::decay_t<decltype(*adl_args::adl_begin(std::declval<Range>()))>;
7272

7373
template<class F1, class... Fs>
74-
struct overload_set : F1, overload_set<Fs...>
74+
struct overload_set;
75+
76+
template<class F1, class F2, class... Fs>
77+
struct overload_set<F1, F2, Fs...> : F1, overload_set<F2, Fs...>
7578
{
7679
using F1::operator();
77-
using overload_set<Fs...>::operator();
78-
overload_set(F1 f1, Fs... fs) : F1(f1), overload_set<Fs...>(fs...)
80+
using overload_set<F2, Fs...>::operator();
81+
overload_set(F1 f1, F2 f2, Fs... fs)
82+
: F1(std::move(f1)), overload_set<F2, Fs...>(std::move(f2), std::move(fs)...)
7983
{}
8084
};
8185

8286
template<class F1>
8387
struct overload_set<F1> : F1
8488
{
8589
using F1::operator();
86-
overload_set(F1 f1) : F1(f1)
90+
overload_set(F1 f1) : F1(std::move(f1))
8791
{}
8892
};
8993

9094
template<class... Fs>
9195
overload_set<Fs...> overload(Fs... fs)
9296
{
93-
return {fs...};
97+
return {std::move(fs)...};
9498
}
9599

100+
template<class F>
101+
void each_arg(F) {}
102+
103+
#ifdef __clang__
104+
template<class F, class T, class... Ts>
105+
void each_arg(F f, T&& x, Ts&&... xs)
106+
{
107+
f(std::forward<T>(x));
108+
args::each_arg(f, std::forward<Ts>(xs)...);
109+
}
110+
#else
96111
template<class F, class... Ts>
97112
void each_arg(F f, Ts&&... xs)
98113
{
99-
(void)std::initializer_list<int>{((void)f(std::forward<Ts>(xs)), 0)...};
114+
(void)std::initializer_list<int>{((void)(f(std::forward<Ts>(xs))), 0)...};
100115
}
101-
102-
template<class F>
103-
void each_arg(F) {}
116+
#endif
104117

105118
std::vector<std::string> wrap(const std::string& text, unsigned int line_length = 72)
106119
{
@@ -186,7 +199,7 @@ auto get_ ## name() ARGS_RETURNS(detail::get_ ## name ## _impl<T>(rank<1>{}));
186199
template<class T>
187200
std::string get_command_type_name()
188201
{
189-
std::string name = get_type_name<T>();
202+
std::string name = args::get_type_name<T>();
190203
auto i = name.find("::");
191204
if (i != std::string::npos) name = name.substr(i+2);
192205
return trim(name, [](char c) { return c == '_'; });
@@ -254,13 +267,13 @@ std::string type_to_help_impl(rank<0>)
254267
template<class T>
255268
auto type_to_help_impl(rank<1>) -> typename std::enable_if<(is_container<T>() and not std::is_convertible<T, std::string>()), std::string>::type
256269
{
257-
return type_to_help_impl<value_of<T>>(rank<1>{}) + "...";
270+
return args::type_to_help_impl<value_of<T>>(rank<1>{}) + "...";
258271
}
259272

260273
template<class T>
261274
std::string type_to_help(const T&)
262275
{
263-
return "[" + type_to_help_impl<T>(rank<1>{}) + "]";
276+
return "[" + args::type_to_help_impl<T>(rank<1>{}) + "]";
264277
}
265278

266279
struct argument
@@ -296,7 +309,7 @@ struct argument
296309

297310
bool write(const std::string& s)
298311
{
299-
write_value(s);
312+
this->write_value(s);
300313
count++;
301314
for(auto&& f:eager_callbacks) f(*this);
302315
return not eager_callbacks.empty();
@@ -330,10 +343,10 @@ struct context
330343
void parse(T&& x, Ts&&... xs)
331344
{
332345
argument arg;
333-
arg.write_value = [&x](const std::string& s) { write_value_to(x, s); };
334-
arg.type = get_argument_type(x);
335-
arg.metavar = type_to_help(x);
336-
each_arg(overload(
346+
arg.write_value = [&x](const std::string& s) { args::write_value_to(x, s); };
347+
arg.type = args::get_argument_type(x);
348+
arg.metavar = args::type_to_help(x);
349+
args::each_arg(args::overload(
337350
[&, this](const std::string& name) { arg.flags.push_back(name); },
338351
[&, this](auto&& attribute) -> decltype(attribute(x, *this, arg), void()) { attribute(x, *this, arg); }
339352
), std::forward<Ts>(xs)...);
@@ -352,7 +365,7 @@ struct context
352365

353366
void show_help_col(std::string item, std::string help, int width, int total_width) const
354367
{
355-
auto txt = wrap(help, total_width-width-2);
368+
auto txt = args::wrap(help, total_width-width-2);
356369
assert(!txt.empty());
357370
std::cout << " " << std::setw(width) << item << " " << txt[0] << std::endl;
358371
std::for_each(txt.begin()+1, txt.end(), [&](std::string line)
@@ -380,21 +393,21 @@ struct context
380393

381394
std::cout << std::endl;
382395
std::cout << std::endl;
383-
for(auto line:wrap(description, total_width-2)) std::cout << " " << line << std::endl;
396+
for(auto line:args::wrap(description, total_width-2)) std::cout << " " << line << std::endl;
384397
std::cout << std::endl;
385398
std::cout << "Options: " << std::endl << std::endl;
386399
// TODO: Switch to different format when width > 40
387400
for(auto&& arg:arguments)
388401
{
389-
show_help_col(arg.get_flags(), arg.help, width, total_width);
402+
this->show_help_col(arg.get_flags(), arg.help, width, total_width);
390403
}
391404
if (subcommands.size() > 0)
392405
{
393406
std::cout << std::endl;
394407
std::cout << "Commands: " << std::endl << std::endl;
395408
for(auto&& p:subcommands)
396409
{
397-
show_help_col(p.first, p.second.help, width, total_width);
410+
this->show_help_col(p.first, p.second.help, width, total_width);
398411
}
399412
}
400413
std::cout << std::endl;
@@ -436,7 +449,7 @@ auto eager_callback(F f)
436449
template<class F>
437450
auto action(F f)
438451
{
439-
return eager_callback([=](auto&&...) { f(); });
452+
return args::eager_callback([=](auto&&...) { f(); });
440453
}
441454

442455
template<class T>
@@ -511,13 +524,13 @@ template<class... Ts, class T>
511524
context<T&, Ts...> build_context(T& cmd)
512525
{
513526
context<T&, Ts...> ctx;
514-
assign_subcommands(rank<1>{}, ctx, cmd);
527+
args::assign_subcommands(rank<1>{}, ctx, cmd);
515528
ctx.parse(nullptr, "-h", "--help", args::help("Show help"),
516-
eager_callback([](std::nullptr_t, const auto& c, const argument&)
529+
args::eager_callback([](std::nullptr_t, const auto& c, const argument&)
517530
{
518531
c.show_help(get_name<T>(), get_help<T>(), get_options_metavar<T>());
519532
}));
520-
try_parse(rank<1>{}, cmd, [&](auto&&... xs)
533+
args::try_parse(rank<1>{}, cmd, [&](auto&&... xs)
521534
{
522535
ctx.parse(std::forward<decltype(xs)>(xs)...);
523536
});
@@ -538,7 +551,7 @@ std::tuple<std::string, std::string> parse_attached_value(const std::string& s)
538551
if (s[1] == '-')
539552
{
540553
auto it = std::find(s.begin(), s.end(), '=');
541-
return std::make_tuple(std::string(s.begin(), it), pop_string(it, s.end()));
554+
return std::make_tuple(std::string(s.begin(), it), args::pop_string(it, s.end()));
542555
}
543556
else if (s.size() > 2)
544557
{
@@ -566,7 +579,7 @@ auto try_run(rank<1>, T& x, Ts&&...) ARGS_RETURNS(x.run())
566579
template<class T, class... Ts>
567580
void parse(T& cmd, std::deque<std::string> a, Ts&&... xs)
568581
{
569-
auto ctx = build_context<Ts...>(cmd);
582+
auto ctx = args::build_context<Ts...>(cmd);
570583

571584
bool capture = false;
572585
std::string core;
@@ -576,7 +589,7 @@ void parse(T& cmd, std::deque<std::string> a, Ts&&... xs)
576589
{
577590
// TODO: Check if flag exists
578591
std::string value;
579-
std::tie(core, value) = parse_attached_value(x);
592+
std::tie(core, value) = args::parse_attached_value(x);
580593
if (ctx[core].type == argument_type::none)
581594
{
582595
capture = false;
@@ -610,7 +623,7 @@ void parse(T& cmd, std::deque<std::string> a, Ts&&... xs)
610623
}
611624
ctx.post_process();
612625

613-
try_run(rank<2>{}, cmd, xs...);
626+
args::try_run(rank<2>{}, cmd, xs...);
614627
}
615628

616629
template<class T, class... Ts>
@@ -620,7 +633,7 @@ void parse(std::deque<std::string> a, Ts&&... xs)
620633
T cmd;
621634
try
622635
{
623-
parse(cmd, std::move(a), xs...);
636+
args::parse(cmd, std::move(a), xs...);
624637
}
625638
catch(const std::exception& ex)
626639
{
@@ -632,7 +645,7 @@ template<class T>
632645
void parse(int argc, char const *argv[])
633646
{
634647
std::deque<std::string> as(argv+1, argv+argc);
635-
parse<T>(as);
648+
args::parse<T>(as);
636649
}
637650

638651
template<class T, class F>
@@ -673,7 +686,7 @@ struct group
673686
subcommand_type sub;
674687
sub.run = [](auto a, auto&&... xs)
675688
{
676-
parse<T>(a, xs...);
689+
args::parse<T>(a, xs...);
677690
};
678691
sub.help = get_help<T>();
679692
subcommands().emplace(get_name<T>(), sub);

test/basic.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <args.hpp>
22
#include "test.hpp"
3-
43
struct single_value_cmd
54
{
65
int count;

0 commit comments

Comments
 (0)