
Hi Guys Below is my current code used to retrieve commandline arguments: int i = 1; while (i < argc) { if (strcmp(argv[i], "-f") == 0) { for (++i; i < argc && strcmp(argv[i], "-s") != 0; ++i) { filearr.push_back(argv[i]); } } else if (strcmp(argv[i], "-s") == 0) { for (++i; i < argc && strcmp(argv[i], "-f") != 0; ++i) { searchtext = argv[i]; } } else { ++i; } } As you can see, its not very scalable. I am thinking of adding another feature args but it'll become difficult to manage. Is there anything on boost which does the same thing albeit with alot less code ?

Dear Shaolin, First, please get acquainted with this, it is really useful to read this: http://www.boost.org/doc/libs Second, boost::program_options may help you, if I understand what you need. Please, make some investigation and tries - before asking other boost users about some question. It will make people think you respect time of others. 2009/8/23 Shaolin <shaolinfinest@gmail.com>:

Hi! Take a look at boost program_options library: http://www.boost.org/doc/libs/1_39_0/doc/html/program_options.html Regards, Ovanes On Sun, Aug 23, 2009 at 7:31 PM, Shaolin <shaolinfinest@gmail.com> wrote:

Thanks guys. I have constructed some code but am getting some errors. I am trying to use a vector to hold several values but everytime I execute it I get a page worth of errors. Code below: po::options_description desc("Available Options"); desc.add_options() ("file", po::value< vector<string> >(), "specify files to search") ; po::variables_map vm; po::store(po::parse_command_line(ac, av, desc), vm); po::notify(vm); if (vm.count("file")) { cout << "Files selected: " << vm["file"].as< vector<string> >() << "\n"; } else { cout << "No Files selected.\n"; } The error is being caused by the following line: cout << "Files selected: " << vm["file"].as< vector<string> >() << "\n"; Here is the error message: play.cpp: In function ‘int main(int, char**)’: play.cpp:24: error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)(& std::cout)), ((const char*)"Files selected: ")) << ((const boost::program_options::variable_value*)vm.boost::program_options::variables_map::operator[](((const std::string&)(& std::basic_string<char, std::char_traits<char>, std::allocator<char> >(((const char*)"file"), ((const std::allocator<char>&)((const std::allocator<char>*)(& std::allocator<char>()))))))))->boost::program_options::variable_value::as [with T = std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >]()’ /usr/include/c++/4.3/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:131: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:177: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/bits/ostream.tcc:97: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:184: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/bits/ostream.tcc:111: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:208: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:217: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/ostream:229: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>] /usr/include/c++/4.3/bits/ostream.tcc:125: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>] . . . 2009/8/23 Ovanes Markarian <om_boost@keywallet.com>

On Sun, Aug 23, 2009 at 5:48 PM, Shaolin<shaolinfinest@gmail.com> wrote:
The same way that you would stream any normal vector: vector<string> &files = vm["file"].as< vector<string> >(); vector<string>::const_iterator iter = files.begin(); cout << "Files selected: "; for(;iter!=files.end();++iter) { cout << *iter << ";"; } cout << "\n"; If you do not know how to do that then you may want to read up on some C++ tutorials first before you start delving into something as big as LLVM. Consequently, if you have Boost trunk installed, then you could do this as well since it does support streaming vectors: #include <boost/spirit/include/karma.hpp> using namespace boost::spirit::karma; using namespace boost::spirit::ascii; generate(cout, "Files selected: " << (*char_)%';' << eol, vm["file"].as< vector<string> >());

Ok, I have managed to get it to work, however, the file param only accepts one value. How can I get several different values for one param ? e.g. --file file1.txt file2.txt file3.txt if (vm.count("file")) { cout << "Files selected: "; vector<string> files = vm["file"].as< vector<string> >(); for(int i=0; i<files.size(); ++i) { cout << files[i]; } cout << "\n"; } 2009/8/24 OvermindDL1 <overminddl1@gmail.com>

On Sun, Aug 23, 2009 at 7:08 PM, Shaolin<shaolinfinest@gmail.com> wrote:
As-is I bet it accepts it like: --file file1.txt --file file2.txt --file file3.txt If you want to to accept arguments like: file1.txt file2.txt file3.txt, assuming you have no other repeatable types, then you need to specify a positional arguments function for file, like: positional_options_description pd; pd.add("file", -1); The Boost.Program_Options documentation details all of this.

On Sun, Aug 23, 2009 at 8:20 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
That is assuming you wanted an endl at the end of each name, a usual delimiter is something like ';' or so, so this instead: cout << "Files selected: "; BOOST_FOREACH(string& sFile, vm["file"].as< vector<string> >()) cout << sFile.c_str() << ";"; cout << "\n"; Although the karma version that Hartmut posted is still the fastest way to do it (in terms of execution speed): generate(sink, "Files selected: " << string % ';' << eol, vm["file"].as< vector<string> >());

Hi Overmind, Really? Thank you for that tip! That brings me to a few questions (I was just testing it and couldn't get it to work quickly). What is the sink? I think i can just replace that with cout, right? Actually, no, that gets me an compile error "boost/spirit/home/karma/detail/output_iterator.hpp(295) : error C2675: unary '++' : 'std::ostream' does not define this operator or a conversion to a type acceptable to the predefined operator". ok, what i got now is: #include <boost/spirit/include/karma.hpp> namespace bk = boost::spirit::karma; namespace ba = boost::spirit::ascii; vector<string> vsUnrecog = collect_unrecognized(parsed.options,po::exclude_positional); bk::generate(cout, "Option \"" << ba::string % '\" not recognized' << bk::eol, vsUnrecog); Where do those sinks come from and how do I make a simple sink that writes to stdout, just like cout does? By the way, doen't your code both use ";" and newline (eol) as delimiters? Best, Dee On Mon, Aug 24, 2009 at 10:42 AM, OvermindDL1<overminddl1@gmail.com> wrote:

I used 'sink' as a placeholder for any output iterator, so in your case the easiest is to construct an ostream_iterator<char>(cout).
By the way, doen't your code both use ";" and newline (eol) as delimiters?
';' is used as the delimiter in between the elements of the vector (string % ';': in Spirit operator% is used as the shortcut for 'list'), and eol is used as the closing newline. Regards Hartmut

Hi Harmut, Thank you for the answers. However, I am still having some trouble and i figure it out following the documentation on the list operator. I am trying to produce an output like below: Options not recognized: "dd" "-e" "rrty" However, bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string % "\"" << bk::eol) << bk::eol, vsUnrecog); does not do the trick and bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" % ba::string % "\"" << bk::eol) << bk::eol, vsUnrecog); fails with "..\Dependency\boost\boost/spirit/home/karma/string/lit.hpp(108) : error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************(__thiscall boost::spirit::karma::any_string<CharEncoding,Tag>::generate::string_not_usable_without_attribute::* ***********)(void)' to 'boost::mpl::assert<false>::type'" (which I guess is not the way it should fail? Shouldnt there be a nice assertion message or is this it? no experience with it really) What am I missing here? Best and thanks, Dee On Mon, Aug 24, 2009 at 11:21 AM, Hartmut Kaiser<hartmut.kaiser@gmail.com> wrote:

Oops, the situation is not as bad as i noted in my last message, bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string % ("\"" << bk::eol)) << "\"" << bk::eol, vsUnrecog); Does almost what it should, except the prefix is only diplayed for the first item in the list (it thus doesn't seem to belong to the list. Output wanted: Options not recognized: "dd" "-e" "rrty" Output got: Options not recognized: "dd" -e" rrty" It seems unneccesarily complex though, and I have to put "\"" << bk::eol in the code twice, is that really necessary? Thank you for your time, Best, Diederick On Mon, Aug 24, 2009 at 12:03 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:

On Sun, Aug 23, 2009 at 10:14 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
Er, do this I mean (adding spacing to help clarify things for you to): bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string << '\"') % bk::eol ,vsUnrecog); To describe it, it first prints out a string, then the % operator has two part, the left side ('\"' << ba::string << '\"'), and the right bk::eol, meaning that the left side is run for each element in a list separated by returns.

On Sun, Aug 23, 2009 at 10:42 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
If that did not work, I am surprised, perhaps hartmut could see why, he is the expert here. :) Try: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string << '\"') >> *("\n \"" << ba::string << '\"') ,vsUnrecog); More verbose, but it should do the same thing as the top one, see if it works, I am curious why the previous one did not know, I may have to try it myself...

That also gave me compilation errors: ..\Dependency\boost\boost/spirit/home/karma/generate.hpp(72) : error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************(__thiscall boost::spirit::karma::generate::error_invalid_expression::* ***********)(Expr)' to 'boost::mpl::assert<false>::type' ..\Dependency\boost\boost/spirit/home/karma/generate.hpp(76) : error C2039: 'generate' : is not a member of 'boost::proto::exprns_::expr<Tag,Args,Arity>' Below, please find a minimal example. Thank you for your continued help! Best, Dee --- #include <vector> #include <string> #include <iostream> using namespace std; #include <boost/spirit/include/karma.hpp> namespace bk = boost::spirit::karma; namespace ba = boost::spirit::ascii; int main() { vector<string> vsTest; vsTest.push_back("test"); vsTest.push_back("t2"); vsTest.push_back("t3"); bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string % ("\"" << bk::eol)) << "\"" << bk::eol, vsTest); bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << ('\"' << ba::string << '\"') % bk::eol << bk::eol, vsTest); return 0; } --- On Mon, Aug 24, 2009 at 1:01 PM, OvermindDL1<overminddl1@gmail.com> wrote:

On Sun, Aug 23, 2009 at 11:20 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
This is what I get when I compile with your test: 1>------ Build started: Project: pure_testing, Configuration: Release Win32 ------ 1>Compiling... 1>main.cpp 1>using native typeof 1>Linking... 1>Generating code 1>Finished generating code 1>Embedding manifest... 1>Build Time 0:27 1>Build log was saved at "file://r:\Programming_Projects\pure_testing\Release\BuildLog.htm" 1>pure_testing - 0 error(s), 0 warning(s) ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== Looks like it works perfect to me. You are using Boost Trunk like I stated in my first post in this thread, right? You should still use this grammar though, it is the best: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string << '\"') % bk::eol ,vsTest); And yes, I confirmed it compiles and runs as you want.

Dear OvermindDL1, That solves the issue then, I'm using Boost 1.39 ;) Let me try trunk, all should work fine then. I have seen the other thread in which the location of sprit v2.1's doc were disclosed, however i didn't connect those threads for some reason. Thanks again! Best, Diederick On Mon, Aug 24, 2009 at 1:36 PM, OvermindDL1<overminddl1@gmail.com> wrote:

Yup, now it works. For reference, I got rid of the duplicated bk::eol also by using the folloing code: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << (" \"" << ba::string << '"' << bk::eol) % "", vsTest); Not putting an empty char array after the modulus operator would be invalid C++ and is thus required. Thanks again, Best, Diederick On Mon, Aug 24, 2009 at 1:45 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:

On Sun, Aug 23, 2009 at 11:58 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
Why not just use what I posted? There-for you will not have a trailing eol, if you want a trailing eol then you should just loop it, not list it, do this: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << +(" \"" << ba::string << '"' << bk::eol), vsTest); The + in front of that loop section means 1 or more, you can also use * for zero or more, but since you should be testing you array size before you call this anyway, you know you have at least one, you can also not do an array size test outside of it and do it inside the parsing function but there is not much point here it is so simple. :)

Ha! cool, thanks again. I'll have to delve into this some more when i need it more. I can see how these functions can also provide very nice ways of writing numeric vectors to file. Things will get slightly more complicated for some other usage cases i have, so i'll have to read up on that. I'll post back when I can figure it out. One of them is a matrix (class written by my colleague), i guess i could loop over the rows and then throw the vector into the generator, or would there be more efficient ways/tricks? Best, Diederick On Mon, Aug 24, 2009 at 2:17 PM, OvermindDL1<overminddl1@gmail.com> wrote:

On Mon, Aug 24, 2009 at 12:53 AM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
No point copying it, if there are public accessors, then Spirit can use them, we can show you how to make binders for such things, and if it follows STL's interface design, there may be no need to any binders anyway. Spirit is designed to be easy, fast, and powerful. :) There is also a spirit mailing list you can join as well, can get even more help there.

Yup, now it works.
Good.
If you don't need any separators in between the list items you could write: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << *(" \"" << ba::string << '"') << bk::eol, vsTests); (which is the equivalent of a Kleene Star). BTW, Karma has a different API allowing to directly integrate the code above with output streams: cout << karma::format( *(" \"" << ascii::string << '"') << eol , vsTest ); where format is a std::stream manipulator. Regards Hartmut

OvermindDL1 The code you specifed to retrieve several values for one param doesn't work: po::positional_options_description pd; pd.add("file", -1); I tried value< vector<string> >()->multitoken() which did the trick, however all the text it treated as one string when each word should be placed into its only place in the vector. 2009/8/24 Hartmut Kaiser <hartmut.kaiser@gmail.com>

On Sun, Aug 23, 2009 at 11:45 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
Yea, Spirit2.1 is basically finished, just the docs are really all the is left, and more 3rd-party utilities in the repository. :) Boost 1.39 has Spirit2, Spirit2.1 is a complete and full rewrite of Spirit2, the syntax is similar but it compiles faster, runs faster, is *much* easier to make your own new terminals in, etc... And it is a lot more complete now too. :)

On Sun, Aug 23, 2009 at 10:03 PM, Diederick C. Niehorster<dcnieho@gmail.com> wrote:
Maybe try this: bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << ('\"' << ba::string << '\"') % bk::eol) << bk::eol, vsUnrecog); You were doing a list of a list of a literal in such a way that cannot be done, cannot take a list of a literal. :p

Thank you for the suggestion. bk::generate(ostream_iterator<char>(cout), "Command line options not recognized:\n" << ('\"' << ba::string << '\"') % bk::eol << bk::eol, vsUnrecog); however gets me four compiler errors: ..\Dependency\boost\boost/spirit/home/karma/string/lit.hpp(94) : error C2784: 'bool boost::spirit::karma::detail::string_generate(OutputIterator &,const Char *,CharEncoding,Tag)' : could not deduce template argument for 'const Char *' from 'const boost::iterator_range<IteratorT>' ..\Dependency\boost\boost/spirit/home/karma/string/lit.hpp(94) : error C2784: 'bool boost::spirit::karma::detail::string_generate(OutputIterator &,const std::basic_string<Char,Traits,Allocator> &,CharEncoding,Tag)' : could not deduce template argument for 'const std::basic_string<Char,Traits,Allocator> &' from 'const boost::iterator_range<IteratorT>' ..\Dependency\boost\boost/spirit/home/karma/string/lit.hpp(94) : error C2780: 'bool boost::spirit::karma::detail::string_generate(OutputIterator &,const std::basic_string<Char,Traits,Allocator> &)' : expects 2 arguments - 4 provided ..\Dependency\boost\boost/spirit/home/karma/string/lit.hpp(94) : error C2780: 'bool boost::spirit::karma::detail::string_generate(OutputIterator &,const Char *)' : expects 2 arguments - 4 provided Best, Diederick On Mon, Aug 24, 2009 at 12:21 PM, OvermindDL1<overminddl1@gmail.com> wrote:

What version are you using? Unfortunately, the versions currently distributed with Boost (that's Spirit V2) is more like a beta as it has some bugs and isn't feature complete (that's why we didn't put it in the front row, keeping Spirit.Classic as the main version to use). OTOH, the code in Boost SVN trunk (that's V2.1) is really very stable and has matured a lot. If you want to experiment with Karma this is definitely the version to use. The expressions described by OvermindDL1 should work, so I suspect you're trying to make it working using the outdated code... HTH Regards Hartmut

I'm writing some test case generators and, for the umpteenth time, having to craft combination and permutation generation loops. I see that there is a "permutation iterator" that scrambles ranges. That's a good and useful tool but it isn't enough for what I have in mind. I'd like a set of tools that will provide both exhaustive and random combinations and permutations of N items from M item sets or multisets (represented in a variety of concrete ways and with M >= N). Admitting multisets moves the problem from first-year to second- or third-year level. I like to keep things interesting ;-) Any suggestions? I am putting some effort into generalizing the interface to the code I'm hacking on now but I doubt my management will permit me to contribute it to boost. Maybe, since it is used only for testing. We'll see. But if somebody else started the ball rolling I could take pot shots at their work. -swn PS: The specification above could be expanded to include a pairwise test case generator, or that could be considered another library suggestion. These things are usually needed at a utility level rather than inside a compiled test driver but there are exceptions. See http://www.pairwise.org/tools.asp .

On Mon, Aug 24, 2009 at 09:51:09AM -0500, Stephen Nuchia wrote:
These, and many other algorithms, are described in the "fxt book": http://www.jjj.de/fxt/
participants (9)
-
Diederick C. Niehorster
-
Hartmut Kaiser
-
Ovanes Markarian
-
OvermindDL1
-
Roman Shmelev
-
Shaolin
-
Stephen Nuchia
-
Steven Watanabe
-
Zeljko Vrba