Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
cmdline.h
Go to the documentation of this file.
1// GitHub source: from https://github.com/tanakh/cmdline
2// Modifications made in-place to remove the use of exceptions,
3// flagged with HALIDE_WITH_EXCEPTIONS
4
5/*
6 Copyright (c) 2009, Hideyuki Tanaka
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 * Neither the name of the <organization> nor the
17 names of its contributors may be used to endorse or promote products
18 derived from this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
21 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
24 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
32#pragma once
33
34#include <algorithm>
35#include <cstdlib>
36#include <cstring>
37#include <iostream>
38#include <map>
39#include <sstream>
40#include <stdexcept>
41#include <string>
42#include <typeinfo>
43#include <vector>
44
45#if defined(_MSC_VER) && !defined(NOMINMAX)
46#define NOMINMAX
47#endif
48
49#if !defined(_WIN32)
50#include <cxxabi.h>
51#else
52#include <windows.h>
53#pragma warning(disable : 4091)
54#include <dbghelp.h>
55#pragma comment(lib, "dbghelp.lib")
56#endif
57
58namespace cmdline {
59
60namespace detail {
61
62#ifdef HALIDE_WITH_EXCEPTIONS
63inline void throw_bad_cast() {
64 throw std::bad_cast();
65}
66#else
67inline void throw_bad_cast() {
68 std::cerr << "bad cast\n";
69 exit(1);
70}
71#endif
72
73template<typename Target, typename Source, bool Same>
75public:
76 static Target cast(const Source &arg) {
77 Target ret;
78 std::stringstream ss;
79 if (!(ss << arg && ss >> ret && ss.eof())) {
81 }
82
83 return ret;
84 }
85};
86
87template<typename Target, typename Source>
88class lexical_cast_t<Target, Source, true> {
89public:
90 static Target cast(const Source &arg) {
91 return arg;
92 }
93};
94
95template<typename Source>
96class lexical_cast_t<std::string, Source, false> {
97public:
98 static std::string cast(const Source &arg) {
99 std::ostringstream ss;
100 ss << arg;
101 return ss.str();
102 }
103};
104
105template<typename Target>
106class lexical_cast_t<Target, std::string, false> {
107public:
108 static Target cast(const std::string &arg) {
109 Target ret;
110 std::istringstream ss(arg);
111 if (!(ss >> ret && ss.eof())) {
113 }
114 return ret;
115 }
116};
117
118template<typename T1, typename T2>
119struct is_same {
120 static const bool value = false;
121};
122
123template<typename T>
124struct is_same<T, T> {
125 static const bool value = true;
126};
127
128template<typename Target, typename Source>
129Target lexical_cast(const Source &arg) {
131}
132
133static inline std::string demangle(const std::string &name) {
134#if !defined(_WIN32)
135 int status = 0;
136 char *p = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status);
137 std::string ret(p);
138 free(p);
139 return ret;
140#else
141 char demangled_name[8192];
142 if (UnDecorateSymbolName(name.c_str(), demangled_name, sizeof(demangled_name),
143 UNDNAME_COMPLETE)) {
144 std::string ret(demangled_name);
145 return ret;
146 } else {
147 DWORD error = GetLastError();
148 std::cout << "UnDecorateSymbolName error: " << error << std::endl;
149 return name;
150 }
151#endif
152}
153
154template<class T>
155std::string readable_typename() {
156#ifndef HALIDE_ENABLE_RTTI
157 return "unrecognized type";
158#else
159 return demangle(typeid(T).name());
160#endif
161}
162
163template<class T>
164std::string default_value(T def) {
166}
167
168template<>
169inline std::string readable_typename<std::string>() {
170 return "string";
171}
172
173#ifndef HALIDE_ENABLE_RTTI
174template<>
175inline std::string readable_typename<bool>() {
176 return "bool";
177}
178
179template<>
180inline std::string readable_typename<int>() {
181 return "int";
182}
183#endif
184
185} // namespace detail
186
187//-----
188
189#ifdef HALIDE_WITH_EXCEPTIONS
190class cmdline_error : public std::exception {
191public:
192 explicit cmdline_error(const std::string &msg)
193 : msg(msg) {
194 }
195 ~cmdline_error() throw() override = default;
196 const char *what() const throw() override {
197 return msg.c_str();
198 }
199
200private:
201 std::string msg;
202};
203inline void throw_cmdline_error(const std::string &s) {
204 throw cmdline::cmdline_error(s);
205}
206#else
207inline void throw_cmdline_error(const std::string &s) {
208 std::cerr << "error: " << s << "\n";
209 exit(1);
210}
211#endif
212
213template<class T>
215 T operator()(const std::string &str) {
216 return detail::lexical_cast<T>(str);
217 }
218};
219
220template<class T>
222 range_reader(const T &low, const T &high)
223 : low(low), high(high) {
224 }
225 T operator()(const std::string &s) const {
226 T ret = default_reader<T>()(s);
227 if (!(ret >= low && ret <= high)) {
228 throw_cmdline_error("range_error");
229 }
230 return ret;
231 }
232
233private:
234 T low, high;
235};
236
237template<class T>
238range_reader<T> range(const T &low, const T &high) {
239 return range_reader<T>(low, high);
240}
241
242template<class T>
244 T operator()(const std::string &s) {
245 T ret = default_reader<T>()(s);
246 if (std::find(alt.begin(), alt.end(), ret) == alt.end()) {
248 }
249 return ret;
250 }
251 void add(const T &v) {
252 alt.push_back(v);
253 }
254
255private:
256 std::vector<T> alt;
257};
258
259template<class T>
261 oneof_reader<T> ret;
262 ret.add(a1);
263 return ret;
264}
265
266template<class T>
268 oneof_reader<T> ret;
269 ret.add(a1);
270 ret.add(a2);
271 return ret;
272}
273
274template<class T>
275oneof_reader<T> oneof(T a1, T a2, T a3) {
276 oneof_reader<T> ret;
277 ret.add(a1);
278 ret.add(a2);
279 ret.add(a3);
280 return ret;
281}
282
283template<class T>
284oneof_reader<T> oneof(T a1, T a2, T a3, T a4) {
285 oneof_reader<T> ret;
286 ret.add(a1);
287 ret.add(a2);
288 ret.add(a3);
289 ret.add(a4);
290 return ret;
291}
292
293template<class T>
294oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5) {
295 oneof_reader<T> ret;
296 ret.add(a1);
297 ret.add(a2);
298 ret.add(a3);
299 ret.add(a4);
300 ret.add(a5);
301 return ret;
302}
303
304template<class T>
305oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6) {
306 oneof_reader<T> ret;
307 ret.add(a1);
308 ret.add(a2);
309 ret.add(a3);
310 ret.add(a4);
311 ret.add(a5);
312 ret.add(a6);
313 return ret;
314}
315
316template<class T>
317oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7) {
318 oneof_reader<T> ret;
319 ret.add(a1);
320 ret.add(a2);
321 ret.add(a3);
322 ret.add(a4);
323 ret.add(a5);
324 ret.add(a6);
325 ret.add(a7);
326 return ret;
327}
328
329template<class T>
330oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) {
331 oneof_reader<T> ret;
332 ret.add(a1);
333 ret.add(a2);
334 ret.add(a3);
335 ret.add(a4);
336 ret.add(a5);
337 ret.add(a6);
338 ret.add(a7);
339 ret.add(a8);
340 return ret;
341}
342
343template<class T>
344oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) {
345 oneof_reader<T> ret;
346 ret.add(a1);
347 ret.add(a2);
348 ret.add(a3);
349 ret.add(a4);
350 ret.add(a5);
351 ret.add(a6);
352 ret.add(a7);
353 ret.add(a8);
354 ret.add(a9);
355 return ret;
356}
357
358template<class T>
359oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10) {
360 oneof_reader<T> ret;
361 ret.add(a1);
362 ret.add(a2);
363 ret.add(a3);
364 ret.add(a4);
365 ret.add(a5);
366 ret.add(a6);
367 ret.add(a7);
368 ret.add(a8);
369 ret.add(a9);
370 ret.add(a10);
371 return ret;
372}
373
374//-----
375
376class parser {
377public:
378 parser() = default;
380 for (auto &option : options) {
381 delete option.second;
382 }
383 }
384
385 void add(const std::string &name,
386 char short_name = 0,
387 const std::string &desc = "") {
388 if (options.count(name)) {
389 throw_cmdline_error("multiple definition: " + name);
390 }
391 options[name] = new option_without_value(name, short_name, desc);
392 ordered.push_back(options[name]);
393 }
394
395 template<class T>
396 void add(const std::string &name,
397 char short_name = 0,
398 const std::string &desc = "",
399 bool need = true,
400 const T def = T()) {
401 add(name, short_name, desc, need, def, default_reader<T>());
402 }
403
404 template<class T, class F>
405 void add(const std::string &name,
406 char short_name = 0,
407 const std::string &desc = "",
408 bool need = true,
409 const T def = T(),
410 F reader = F()) {
411 if (options.count(name)) {
412 throw_cmdline_error("multiple definition: " + name);
413 }
414 options[name] = new option_with_value_with_reader<T, F>(name, short_name, need, def, desc, reader);
415 ordered.push_back(options[name]);
416 }
417
418 void footer(const std::string &f) {
419 ftr = f;
420 }
421
422 void set_program_name(const std::string &name) {
423 prog_name = name;
424 }
425
426 bool exist(const std::string &name) const {
427 if (options.count(name) == 0) {
428 throw_cmdline_error("there is no flag: --" + name);
429 }
430 return options.find(name)->second->has_set();
431 }
432
433 template<class T>
434 const T &get(const std::string &name) const {
435 if (options.count(name) == 0) {
436 throw_cmdline_error("there is no flag: --" + name);
437 }
438#ifndef HALIDE_ENABLE_RTTI
439 const option_with_value<T> *p = reinterpret_cast<const option_with_value<T> *>(options.find(name)->second);
440 return p->get();
441#else
442 const option_with_value<T> *p = dynamic_cast<const option_with_value<T> *>(options.find(name)->second);
443 if (p == nullptr) {
444 throw_cmdline_error("type mismatch flag '" + name + "'");
445 }
446 return p->get();
447#endif
448 }
449
450 const std::vector<std::string> &rest() const {
451 return others;
452 }
453
454 bool parse(const std::string &arg) {
455 std::vector<std::string> args;
456
457 std::string buf;
458 bool in_quote = false;
459 for (std::string::size_type i = 0; i < arg.length(); i++) {
460 if (arg[i] == '\"') {
461 in_quote = !in_quote;
462 continue;
463 }
464
465 if (arg[i] == ' ' && !in_quote) {
466 args.push_back(buf);
467 buf = "";
468 continue;
469 }
470
471 if (arg[i] == '\\') {
472 i++;
473 if (i >= arg.length()) {
474 errors.emplace_back("unexpected occurrence of '\\' at end of string");
475 return false;
476 }
477 }
478
479 buf += arg[i];
480 }
481
482 if (in_quote) {
483 errors.emplace_back("quote is not closed");
484 return false;
485 }
486
487 if (!buf.empty()) {
488 args.push_back(buf);
489 }
490
491 for (auto &arg : args) {
492 std::cout << "\"" << arg << "\"\n";
493 }
494
495 return parse(args);
496 }
497
498 bool parse(const std::vector<std::string> &args) {
499 int argc = static_cast<int>(args.size());
500 std::vector<const char *> argv(argc);
501
502 for (int i = 0; i < argc; i++) {
503 argv[i] = args[i].c_str();
504 }
505
506 return parse(argc, &argv[0]);
507 }
508
509 bool parse(int argc, const char *const argv[]) {
510 errors.clear();
511 others.clear();
512
513 if (argc < 1) {
514 errors.emplace_back("argument number must be longer than 0");
515 return false;
516 }
517 if (prog_name.empty()) {
518 prog_name = argv[0];
519 }
520
521 std::map<char, std::string> lookup;
522 for (auto &option : options) {
523 if (option.first.empty()) {
524 continue;
525 }
526 char initial = option.second->short_name();
527 if (initial) {
528 if (lookup.count(initial) > 0) {
529 lookup[initial] = "";
530 errors.push_back(std::string("short option '") + initial + "' is ambiguous");
531 return false;
532 } else {
533 lookup[initial] = option.first;
534 }
535 }
536 }
537
538 for (int i = 1; i < argc; i++) {
539 if (strncmp(argv[i], "--", 2) == 0) {
540 const char *p = strchr(argv[i] + 2, '=');
541 if (p) {
542 std::string name(argv[i] + 2, p);
543 std::string val(p + 1);
544 set_option(name, val);
545 } else {
546 std::string name(argv[i] + 2);
547 if (options.count(name) == 0) {
548 errors.push_back("undefined option: --" + name);
549 continue;
550 }
551 if (options[name]->has_value()) {
552 if (i + 1 >= argc) {
553 errors.push_back("option needs value: --" + name);
554 continue;
555 } else {
556 i++;
557 set_option(name, argv[i]);
558 }
559 } else {
560 set_option(name);
561 }
562 }
563 } else if (strncmp(argv[i], "-", 1) == 0) {
564 if (!argv[i][1]) {
565 continue;
566 }
567 char last = argv[i][1];
568 for (int j = 2; argv[i][j]; j++) {
569 last = argv[i][j];
570 if (lookup.count(argv[i][j - 1]) == 0) {
571 errors.push_back(std::string("undefined short option: -") + argv[i][j - 1]);
572 continue;
573 }
574 if (lookup[argv[i][j - 1]].empty()) {
575 errors.push_back(std::string("ambiguous short option: -") + argv[i][j - 1]);
576 continue;
577 }
578 set_option(lookup[argv[i][j - 1]]);
579 }
580
581 if (lookup.count(last) == 0) {
582 errors.push_back(std::string("undefined short option: -") + last);
583 continue;
584 }
585 if (lookup[last].empty()) {
586 errors.push_back(std::string("ambiguous short option: -") + last);
587 continue;
588 }
589
590 if (i + 1 < argc && options[lookup[last]]->has_value()) {
591 set_option(lookup[last], argv[i + 1]);
592 i++;
593 } else {
594 set_option(lookup[last]);
595 }
596 } else {
597 others.emplace_back(argv[i]);
598 }
599 }
600
601 for (auto &option : options) {
602 if (!option.second->valid()) {
603 errors.push_back("need option: --" + std::string(option.first));
604 }
605 }
606
607 return errors.empty();
608 }
609
610 void parse_check(const std::string &arg) {
611 if (!options.count("help")) {
612 add("help", '?', "print this message");
613 }
614 check(0, parse(arg));
615 }
616
617 void parse_check(const std::vector<std::string> &args) {
618 if (!options.count("help")) {
619 add("help", '?', "print this message");
620 }
621 check(args.size(), parse(args));
622 }
623
624 void parse_check(int argc, char *argv[]) {
625 if (!options.count("help")) {
626 add("help", '?', "print this message");
627 }
628 check(argc, parse(argc, argv));
629 }
630
631 std::string error() const {
632 return !errors.empty() ? errors[0] : "";
633 }
634
635 std::string error_full() const {
636 std::ostringstream oss;
637 for (const auto &error : errors) {
638 oss << error << "\n";
639 }
640 return oss.str();
641 }
642
643 std::string usage() const {
644 std::ostringstream oss;
645 oss << "usage: " << prog_name << " ";
646 for (const auto &o : ordered) {
647 if (o->must()) {
648 oss << o->short_description() << " ";
649 }
650 }
651
652 oss << "[options] ... " << ftr << "\n";
653 oss << "options:\n";
654
655 size_t max_width = 0;
656 for (const auto &o : ordered) {
657 max_width = std::max(max_width, o->name().length());
658 }
659 for (const auto &o : ordered) {
660 if (o->short_name()) {
661 oss << " -" << o->short_name() << ", ";
662 } else {
663 oss << " ";
664 }
665
666 oss << "--" << o->name();
667 for (size_t j = o->name().length(); j < max_width + 4; j++) {
668 oss << ' ';
669 }
670 oss << o->description() << "\n";
671 }
672 return oss.str();
673 }
674
675private:
676 void check(int argc, bool ok) {
677 if ((argc == 1 && !ok) || exist("help")) {
678 std::cerr << usage();
679 exit(0);
680 }
681
682 if (!ok) {
683 std::cerr << error() << "\n"
684 << usage();
685 exit(1);
686 }
687 }
688
689 void set_option(const std::string &name) {
690 if (options.count(name) == 0) {
691 errors.push_back("undefined option: --" + name);
692 return;
693 }
694 if (!options[name]->set()) {
695 errors.push_back("option needs value: --" + name);
696 return;
697 }
698 }
699
700 void set_option(const std::string &name, const std::string &value) {
701 if (options.count(name) == 0) {
702 errors.push_back("undefined option: --" + name);
703 return;
704 }
705 if (!options[name]->set(value)) {
706 errors.push_back("option value is invalid: --" + name + "=" + value);
707 return;
708 }
709 }
710
711 class option_base {
712 public:
713 virtual ~option_base() = default;
714
715 virtual bool has_value() const = 0;
716 virtual bool set() = 0;
717 virtual bool set(const std::string &value) = 0;
718 virtual bool has_set() const = 0;
719 virtual bool valid() const = 0;
720 virtual bool must() const = 0;
721
722 virtual const std::string &name() const = 0;
723 virtual char short_name() const = 0;
724 virtual const std::string &description() const = 0;
725 virtual std::string short_description() const = 0;
726 };
727
728 class option_without_value : public option_base {
729 public:
730 option_without_value(const std::string &name,
731 char short_name,
732 const std::string &desc)
733 : nam(name), snam(short_name), desc(desc) {
734 }
735 ~option_without_value() override = default;
736
737 bool has_value() const override {
738 return false;
739 }
740
741 bool set() override {
742 has = true;
743 return true;
744 }
745
746 bool set(const std::string &) override {
747 return false;
748 }
749
750 bool has_set() const override {
751 return has;
752 }
753
754 bool valid() const override {
755 return true;
756 }
757
758 bool must() const override {
759 return false;
760 }
761
762 const std::string &name() const override {
763 return nam;
764 }
765
766 char short_name() const override {
767 return snam;
768 }
769
770 const std::string &description() const override {
771 return desc;
772 }
773
774 std::string short_description() const override {
775 return "--" + nam;
776 }
777
778 private:
779 std::string nam;
780 char snam;
781 std::string desc;
782 bool has = false;
783 };
784
785 template<class T>
786 class option_with_value : public option_base {
787 public:
788 option_with_value(const std::string &name,
789 char short_name,
790 bool need,
791 const T &def,
792 const std::string &desc)
793 : nam(name), snam(short_name), need(need), def(def), actual(def) {
794 this->desc = full_description(desc);
795 }
796 ~option_with_value() override = default;
797
798 const T &get() const {
799 return actual;
800 }
801
802 bool has_value() const override {
803 return true;
804 }
805
806 bool set() override {
807 return false;
808 }
809
810 bool set(const std::string &value) override {
811#ifdef HALIDE_WITH_EXCEPTIONS
812 try {
813 actual = read(value);
814 has = true;
815 } catch (const std::exception &e) {
816 std::cout << "Exception was caught: " << e.what() << "\n";
817 return false;
818 }
819 return true;
820#else
821 actual = read(value);
822 has = true;
823 return true;
824#endif
825 }
826
827 bool has_set() const override {
828 return has;
829 }
830
831 bool valid() const override {
832 if (need && !has) {
833 return false;
834 }
835 return true;
836 }
837
838 bool must() const override {
839 return need;
840 }
841
842 const std::string &name() const override {
843 return nam;
844 }
845
846 char short_name() const override {
847 return snam;
848 }
849
850 const std::string &description() const override {
851 return desc;
852 }
853
854 std::string short_description() const override {
855 return "--" + nam + "=" + detail::readable_typename<T>();
856 }
857
858 protected:
859 std::string full_description(const std::string &desc) {
860 return desc + " (" + detail::readable_typename<T>() +
861 (need ? "" : " [=" + detail::default_value<T>(def) + "]") + ")";
862 }
863
864 virtual T read(const std::string &s) = 0;
865
866 std::string nam;
867 char snam;
868 bool need;
869 std::string desc;
870
871 bool has = false;
872 T def;
873 T actual;
874 };
875
876 template<class T, class F>
877 class option_with_value_with_reader : public option_with_value<T> {
878 public:
879 option_with_value_with_reader(const std::string &name,
880 char short_name,
881 bool need,
882 const T def,
883 const std::string &desc,
884 F reader)
885 : option_with_value<T>(name, short_name, need, def, desc), reader(reader) {
886 }
887
888 private:
889 T read(const std::string &s) override {
890 return reader(s);
891 }
892
893 F reader;
894 };
895
896 std::map<std::string, option_base *> options;
897 std::vector<option_base *> ordered;
898 std::string ftr;
899
900 std::string prog_name;
901 std::vector<std::string> others;
902
903 std::vector<std::string> errors;
904};
905
906} // namespace cmdline
static std::string cast(const Source &arg)
Definition cmdline.h:98
static Target cast(const Source &arg)
Definition cmdline.h:76
void footer(const std::string &f)
Definition cmdline.h:418
std::string error_full() const
Definition cmdline.h:635
void parse_check(const std::vector< std::string > &args)
Definition cmdline.h:617
void add(const std::string &name, char short_name=0, const std::string &desc="")
Definition cmdline.h:385
std::string usage() const
Definition cmdline.h:643
const T & get(const std::string &name) const
Definition cmdline.h:434
parser()=default
bool parse(const std::vector< std::string > &args)
Definition cmdline.h:498
const std::vector< std::string > & rest() const
Definition cmdline.h:450
bool parse(int argc, const char *const argv[])
Definition cmdline.h:509
std::string error() const
Definition cmdline.h:631
void parse_check(int argc, char *argv[])
Definition cmdline.h:624
void add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T(), F reader=F())
Definition cmdline.h:405
bool parse(const std::string &arg)
Definition cmdline.h:454
bool exist(const std::string &name) const
Definition cmdline.h:426
void parse_check(const std::string &arg)
Definition cmdline.h:610
void add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T())
Definition cmdline.h:396
void set_program_name(const std::string &name)
Definition cmdline.h:422
unsigned long DWORD
Definition mini_d3d12.h:182
std::string default_value(T def)
Definition cmdline.h:164
std::string readable_typename< int >()
Definition cmdline.h:180
Target lexical_cast(const Source &arg)
Definition cmdline.h:129
std::string readable_typename()
Definition cmdline.h:155
void throw_bad_cast()
Definition cmdline.h:67
std::string readable_typename< bool >()
Definition cmdline.h:175
std::string readable_typename< std::string >()
Definition cmdline.h:169
oneof_reader< T > oneof(T a1)
Definition cmdline.h:260
range_reader< T > range(const T &low, const T &high)
Definition cmdline.h:238
void throw_cmdline_error(const std::string &s)
Definition cmdline.h:207
const char * strchr(const char *s, int c)
int strncmp(const char *s, const char *t, size_t n)
void free(void *)
T operator()(const std::string &str)
Definition cmdline.h:215
static const bool value
Definition cmdline.h:120
T operator()(const std::string &s)
Definition cmdline.h:244
void add(const T &v)
Definition cmdline.h:251
range_reader(const T &low, const T &high)
Definition cmdline.h:222
T operator()(const std::string &s) const
Definition cmdline.h:225