本文章所有内容源于《BOOST程序库完全开发指南:深入C++“准”标准库(第3版)》第十章
为了使代码可以在不同平台之间相互移植,介绍system库,它封装了操作系统底层的错误代码,为上层提供了一个可移植的统一的处理接口;随后是chrono和cpu_timer库,它延续到第二章的讨论,基于操作系统的API提供高精度的时间功能;第四个是filesystem库,提供跨平台的文件系统处理能力,能够以一直的方式处理不同操作系统中的文件和目录;最后是program_options库,为程序员提供强大的命令行参数解析和程序运行选项配置能力。
1. system
1.1 功能:
封装了操作系统底层的错误代码和错误信息,使调用操作系统功能的程序可以被很容易的移植。它作为基础部件被chrono、filesystem、asio等库调用。
1.2 头文件:
#define BOOST_ERROR_CODE_HEADER_ONLY
#include <boost/system/error_code.hpp>
using namespace boost::system;
1.3 用法:
核心类:
- error_category
- error_code
- error_condition
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
using namespace boost::system;
#include <iostream>
using std::string;
using std::cout;
using std::endl;
class my_category : public error_category //公有继承错误类别
{
public:
virtual const char *name() const BOOST_SYSTEM_NOEXCEPT
{ return "MYAPP_CATEGORY"; }
virtual string message( int ev ) const
{
string msg;
switch(ev) //使用switch产生错误消息
{
case 0:
msg="ok";break;
default:
msg="some error";break;
}
return msg;
}
};
//可以把error_code(偏重操作系统和底层API)转换成error_condition(偏重移植)
/*----------------------错误类型--------------------------*/
void case1()
{
my_category my_cat; //自定义错误类别的实例
error_code ec(10,my_cat); //错误码10,自定义类别
cout << ec.value() << " " << ec.message() << endl;
ec = error_code( 10, system_category() ); //系统错误类别
cout << ec.value() << " " << ec.message() << endl;
}
/*----------------------错误代码--------------------------*/
void case2()
{
std::cout << system_category().name() << std::endl;
error_code ec;
assert(ec.value() == errc::success);
assert(!ec);
assert(ec.category() == system_category());
ec.assign(3L, system_category());
auto econd = ec.default_error_condition();
assert(econd == ec);
assert(econd == system_category().default_error_condition(3L));
std::cout << ec.message() << std::endl;
std::cout << econd.message() << std::endl;
std::cout << econd.value() << std::endl;
}
/*----------------------错误异常--------------------------*/
void case3()
{
try
{
throw system_error(error_code(5, system_category()));
}
catch (system_error& e)
{
std::cout << e.what();
}
}
int main()
{
case1();
case2();
case3();
}
2. chrono
2.1 功能:
chrono库里很多时间概念和date_time类似,但是它更侧重于表达“计算机时间”里的时间,所以是一个很重要的基础不见,被cpu_timer和thread等库所使用
2.2 头文件:
#define BOOST_ERROR_CODE_HEADER_ONLY //无需编译使用system库
#define BOOST_CHRONO_HEADER_ONLY //无需编译即可使用chrono库
#define BOOST_CHRONO_EXTENSIONS //使用扩展功能
#include <boost/chrono.hpp> //chrono库头文件
using namespace boost::chrono;
2.3 用法:
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::cout;
using std::endl;
//#define BOOST_ERROR_CODE_HEADER_ONLY
#define BOOST_CHRONO_HEADER_ONLY
#define BOOST_CHRONO_EXTENSIONS
#include <boost/chrono.hpp>
using namespace boost;
using namespace boost::chrono;
//
typedef duration<long, ratio<30>> half_min; //半分钟
typedef duration<int, ratio<60*15>> quater; //一刻钟
typedef duration<double, ratio<3600*24>> day; //一天
//typedef duration<int,60*60> my_hour; //不能直接用整数
//typedef duration<int,ratio<-10, 1000>> my_ms; //不能用负数
void case1()
{
seconds s(10); //十秒相当于 10*ratio<1>
minutes m(5); //五分钟相当于 5*ratio<60>
hours h(1); //1*ratio<3600>
milliseconds ms(100); //100*ratio<1,1000>
assert(s.count() == 10); //成员函数count用于计数
assert(ms.count() == 100);
s *= 3; //可以乘除数字标量
s += seconds(30); //加建运算必须都是时间长度
s = s - seconds(20);
assert(s < seconds(50)); //比较也必须是时间长度
cout << s << endl; //输出40秒
}
//
void case2()
{
seconds s(10);
minutes m(5);
s += m; //输出310秒,混合使用
cout << s << endl;
//m+= s; //失败,整数类型不能表示小数概念
{
seconds s(10);
typedef duration<double, ratio<60>> my_min;
my_min m(5);
m += s;
cout << m << endl;
}
{
seconds s(40);
auto m = duration_cast<minutes>(s);
cout << m << endl;
seconds s2(301);
cout << duration_cast<minutes>(s2) << endl;
}
{
seconds s(3600 + 50); //1小时+50秒
cout << floor<minutes>(s) << endl; //60分 //floor向下舍入
cout << ceil<minutes>(s) << endl; //61分 四舍五入
cout << round<minutes>(s) << endl; //61分四舍五入到最近,小的向上舍入
cout << round<hours>(s) << endl; //1小时
}
}
//
//时钟
template<typename T>
using clock_desc = clock_string<T, char>;
void case3()
{
cout << clock_desc<system_clock>::name() << endl; //系统启动开始计时
cout << clock_desc<system_clock>::since() << endl;
cout << clock_desc<steady_clock>::name() << endl; //进程启动开始计时
cout << clock_desc<steady_clock>::since() << endl;
cout << clock_desc<process_real_cpu_clock>::name() << endl;
cout << clock_desc<process_real_cpu_clock>::since() << endl;
}
//
void case4()
{
auto tp1 = system_clock::now(); //获取系统时钟的当前时间点
cout << tp1 << endl;
auto d = tp1.time_since_epoch(); //获取自起点以来的时间长度
cout << duration_cast<hours>(d) << endl; //转换为小时
cout << duration_cast<day>(d) << endl; //转换为自定义的天
auto tp2 = tp1 +minutes(1); //1分钟之后的时间点
cout << tp2 << endl;
{
auto tp = steady_clock::now();
cout << tp << endl;
auto d = tp.time_since_epoch();
cout << round<minutes>(d) << endl; //转换分钟
cout << round<hours>(d) << endl;
}
}
//
hours operator"" _h(unsigned long long n) //小时字面意思
{
return hours(n);
}
seconds operator"" _s(unsigned long long n) //秒字面意思
{
return seconds(n);
}
milliseconds operator"" _ms(unsigned long long n) //毫秒字面值
{
return milliseconds(n);
}
void case5()
{
auto h = 5_h;
auto s = 45_s;
auto ms = 200_ms;
cout << h << s << ms << endl;
}
//
void case6()
{
auto tp = system_clock::now(); //当前时间
auto t = system_clock::to_time_t(tp); //转换为time_t结构
cout << std::ctime(&t) << endl; //输出字符串形式的日期
}
//
class steady_timer final
{
private:
typedef boost::chrono::steady_clock clock_type; //定义时钟类型
//typedef clock_type::duration duration_type;
typedef clock_type::time_point time_point_type; //定义时间点类型
typedef boost::chrono::microseconds duration_type; //使用微秒精度
time_point_type m_start = clock_type::now(); //构造时记录时间点
public:
steady_timer() = default;
~steady_timer() = default;
public:
void restart()
{
m_start = clock_type::now();
}
duration_type elapsed() const
{
return round<duration_type>(
clock_type::now() - m_start);
}
};
//
int main()
{
steady_timer t;
case1();
case2();
case3();
case4();
case5();
case6();
cout << t.elapsed() << endl;
}
3. cpu_timer
3.1 功能:
计算cpu的相关时间
3.2 头文件:
#define BOOST_ERROR_CODE_HEADER_ONLY
#include <boost/system/error_code.hpp>
using namespace boost::system;
3.3 用法:
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;
#include <boost/algorithm/string.hpp>
#include <boost/timer/timer.hpp>
using namespace boost::timer;
//
void case1()
{
vector<string> v(10, "monado"); //一个存储字符串的容器
cpu_timer t; //声明同时启动计时器
assert(!t.is_stopped());
for (int i = 0;i < 10000; ++i)
{
boost::join(v, "-"); //Boost的字符串连接算法
}//end for
t.stop(); //暂时计时器
assert(t.is_stopped()); //计时器已经暂停
cout << "pause for a while..." << endl; //标准流输出
cout << "we can do something..." << endl; //不计入时间
t.resume(); //恢复计时器运行
assert(!t.is_stopped());
for(string& x : v)
{ x +=x; }
cout << t.format();
}
//
void case2()
{
const nanosecond_type ms = 1000 * 1000; //毫秒常量
cpu_times ct = {2000 *ms, 1000*ms, 100*ms}; //初始化cpu_times
cout << format(ct, 7); //默认格式输出
}
//2.000 wall, 1.00s user + 0.100s system = 1.100s cpu(55.0%)
//
void case3()
{
cpu_times ct = {2000, 1000, 100 }; //初始化cpu_times
cout << format(ct, 3); //默认格式输出
}
//
int main()
{
case1();
case2();
case3();
}
4. system
4.1 功能:
一个可移植的文件系统操作库做了大量的工作,使用POSIX标准表示文件系统的路径,接口很多类似标准库的容器和迭代器具
4.2 头文件:
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
4.3 用法:
“/”来分隔文件名和目录名,“.”表示当前目录,“…”表示上级目录
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::string;
using std::cout;
using std::endl;
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
namespace fs = boost::filesystem;
//
void case1()
{
path p1("./a_dir");
path p2("/usr/local/lib");
// path p3("c:\\tmp\\test.text");
// path p4("d:/boost/boost/filesystem/");
path p5;
assert(p5.empty());
}
//
void case2()
{
char str[] = "the path is (/root).";
{
path p(str + 13, str + 14);
assert(!p.empty());
p /= "etc";
string filename = "xinetd.conf";
p.append(filename.begin(), filename.end());
cout << p << endl;
cout << system_complete(p) << endl; //返回路径在当前文件系统中的完整路径(绝对路径)
}
{
path p(str + 13, str + 15);
p += "etc";
string filename = "xinetd.conf";
p.concat(filename.begin(), filename.end());
cout << p << endl;
}
path p("/::/*/?/<>");
}
//
void case3()
{
string fname("w+abc.xxx");
assert(!portable_posix_name(fname));
assert(windows_name(fname));
assert(!portable_name("w+()abc.txt") && !portable_name("./abc"));
assert(!portable_directory_name("a.txt") && portable_directory_name("abc"));
assert( portable_file_name("a.bc") && !portable_file_name("y.conf"));
}
//
void case4() //路径处理
{
path p("/usr/local/include/xxx.hpp");
cout << p.string() << endl;
cout << p.parent_path() << endl;
cout << p.stem() << endl;
cout << p.filename() << endl;
cout << p.extension() << endl;
assert(p.is_absolute()); //用于检测path是否是一个绝对(完整)路径,需要依据具体的文件系统的表示
assert(system_complete(p).is_absolute());
cout << p.root_name() << endl;
cout << p.root_directory() << endl;
cout << p.root_path() << endl;
assert(!p.has_root_name());
assert( p.has_root_path());
assert( p.has_parent_path());
//下面这两个可以改变原地址path
cout << p.replace_extension() << endl;
cout << p.replace_extension("hxx") << endl;
cout << p.remove_filename() << endl;
path p1("/test/1.cpp");
path p2("/TEST/1.cpp");
path p3("/abc/1.cpp");
assert(p1 != p2);
assert(p2 < p3);
p = "/boost/tools/libs";
BOOST_FOREACH(auto& x , p)
{
cout << "["<< x << "]"; //输出路径字符串
}
}
//
void case5()
{
path p("/test.txt"); //一个不存在的文件
try
{
file_size(p); //检查文件大小
}
catch(filesystem_error& e) //捕获异常
{
cout << e.path1() << endl;
cout << e.what() << endl;
}
}
//
void case6()
{
assert(status("/dev/null").type() == character_file);
assert(status("/bin").type() == directory_file);
assert(status("/bin/sh").type() == regular_file);
assert((status("/bin/sh").permissions() & owner_exe) == owner_exe);
path root = "/usr/local/include/boost";
assert( is_directory(root));
assert(!exists(root/"nofile"));
assert(!is_symlink(root/"version.hpp"));
assert(!is_other(root/"version.hpp"));
assert( is_regular_file(root/"version.hpp"));
assert(!fs::is_empty(root/"version.hpp"));
}
//
void case7()
{
cout << initial_path() << endl;
cout << current_path() << endl;
// generate a temp file for test
std::ofstream("./test.txt") << "abcd" << std::endl;
//path p("/usr/local/include/boost/version.hpp");
path p("./test.txt");
cout << file_size(p) << endl;
time_t t = last_write_time(p);
last_write_time(p, time(0));
(void)t;
}
//
#include <boost/ratio.hpp>
void case8()
{
using namespace boost;
//const int GBYTES = 1000*1000*1000; //GB,不是GiB
space_info si = space("/home/chrono");
cout << si.capacity / giga::num<< endl;
cout << si.available / giga::num<< endl;
cout << si.free / giga::num<< endl;
}
//
void case9()
{
//namespace fs = boost::filesystem;
path ptest = "./test";
if (exists(ptest))
{
if (fs::is_empty(ptest))
{
remove(ptest) ;
}
else
{
remove_all(ptest);
}
}
assert(!exists(ptest));
create_directory(ptest) ;
copy_file("/usr/local/include/boost/version.hpp", ptest / "a.txt");
assert(exists(ptest / "a.txt"));
rename(ptest / "a.txt", ptest / "b.txt");
assert(exists(ptest / "b.txt"));
create_directories(ptest / "sub_dir1" / "sub_dir1");
}
//
void case10()
{
//directory_iterator end;
//for (directory_iterator pos("/usr/local/lib/");pos != end; ++pos)
//{ cout << *pos << endl; }
string path = "/dev/shm";//"/tmp";
typedef std::pair<directory_iterator, directory_iterator> dir_range;
//dir_range dr(directory_iterator("/usr/local/lib/"),
dir_range dr(directory_iterator(path.c_str()),
directory_iterator());
BOOST_FOREACH(auto& x , dr)
{ cout << x << endl; }
typedef recursive_directory_iterator rd_iterator;
rd_iterator end;
for (rd_iterator pos(path.c_str());pos != end; ++pos)
{
cout << "depth" << pos.depth() << ":" <<*pos << endl;
}
}
//
int main()
{
case1();
case2();
case3();
case4();
//case5();
case6();
case7();
case8();
//case9();
case10();
}
实例1:实现查找文件功能
实例2:实现模糊查找文件功能
实例3:实现拷贝目录功能
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::string;
using std::vector;
using std::cout;
using std::endl;
#include <boost/optional.hpp>
#include <boost/utility/string_ref.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
using namespace boost;
using namespace boost::filesystem;
namespace fs = boost::filesystem;
typedef recursive_directory_iterator rd_iterator;
//
optional<path>
find_file(const path& dir, const string& filename)
{
typedef optional<path> result_type;
if (!exists(dir) ||!is_directory(dir))
{ return result_type(); }
rd_iterator end;
for (rd_iterator pos(dir);pos != end; ++pos)
{
if(!is_directory(*pos) &&
pos->path().filename() == filename)
{ return result_type(pos->path()); }
}
return result_type();
}
void case1()
{
auto r = find_file("/usr/local/include/boost", "version.hpp");
if (r)
{ cout << *r << endl; }
else
{ cout << "file not found." << endl; }
}
//
#include <boost/xpressive/xpressive_dynamic.hpp>
#include <boost/algorithm/string.hpp>
using namespace boost::xpressive;
vector<path> find_files(const path& dir, const string& filename)
{
static xpressive::sregex_compiler rc;
if (!rc[filename].regex_id())
{
string str = replace_all_copy(
replace_all_copy(filename, ".", "\\."),
"*", ".*");
rc[filename] = rc.compile(str);
}
typedef vector<path> result_type;
result_type v;
if (!exists(dir) || !is_directory(dir))
{ return v; }
rd_iterator end;
for (rd_iterator pos(dir);pos != end; ++pos)
{
if(!is_directory(*pos) &&
regex_match(pos->path().filename().string(), rc[filename]))
{
v.push_back(pos->path());
}
}
return v;
}
void case2()
{
auto v = find_files("/usr/local/include/boost/timer", "*.hpp");
cout << v.size() << endl;
for(path &p : v)
{ cout << p << endl; }
}
//
// disable pragma warning
#define BOOST_ALLOW_DEPRECATED_HEADERS
#include <boost/progress.hpp>
size_t copy_files(const path& from_dir, const path& to_dir ,
const string& filename = "*")
{
if (!is_directory(from_dir))
{
cout << "args is not a dir." << endl;
return 0;
}
cout << "prepare for copy, please wait..." << endl;
auto v = find_files(from_dir, filename);
if (v.empty())
{
cout << "0 file copied." << endl;
return 0;
}
cout << "now begin copy files ..." << endl;
path tmp;
progress_display pd(v.size());
for(auto& p : v)
{
tmp = to_dir / p.string().substr(from_dir.string().length());
if (!exists(tmp.parent_path()))
{
create_directories(tmp.parent_path());
}
copy_file(p, tmp);
++pd;
}
cout << v.size() << " file copied." << endl;
return v.size();
}
void case3()
{
copy_files("/usr/local/include/boost/timer", "./t");
}
//
#include <boost/filesystem/fstream.hpp>
namespace newfs = boost::filesystem;
void case4()
{
// generate a temp file for test
std::ofstream("./test.txt") << "abcd" << std::endl;
path p("./test.txt");
newfs::ifstream ifs(p);
assert(ifs.is_open());
cout << ifs.rdbuf();
// remove file
ifs.close();
remove(p);
}
//
int main()
{
case1();
case2();
case3();
case4();
}
5. program_options
4.1 功能:
参数选择器
4.2 头文件:
#include <boost/program_options.hpp>
using namespace boost::program_options;
4.3 用法:
#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;
#include <boost/program_options.hpp>
using namespace boost::program_options;
//
int case1(int argc, char* argv[])
{
options_description opts("demo options");
opts.add_options() //增加两个程序选项
("help", "just a help info") //帮助选项
("filename", value<string>(), "to find a file") //文件名选项
;
variables_map vm; //选项存储map容器
store(parse_command_line(argc, argv, opts), vm); //解析存储
if (vm.count("help")) //处理帮助选项
{
cout << opts << endl; //输出帮助选项
return 0;
}
if (vm.count("filename")) //要查找的文件名
{ cout << "find " << vm["filename"].as<string>() << endl;}
if (vm.empty()) //没有任何选项参数
{ cout << "no options" << endl; }
return 0;
}
int main(int argc, char* argv[]) //需要命令行参数
{
case1(argc, argv);
}
#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;
#include <boost/program_options.hpp>
using namespace boost::program_options;
//
void print_vm(options_description &opts, variables_map &vm)
{
if (vm.empty()) //无参数处理
{
cout << opts << endl; //输出帮助信息
return;
}
if (vm.count("help")) //处理帮助选项
{
cout << opts << endl;
}
//输出查找文件名,因为它有缺省值,故总存在
cout << "find opt:" << vm["filename"].as<string>() << endl;
if (vm.count("dir")) //处理搜索路径
{
cout << "dir opt:";
for(auto& str:
vm["dir"].as<vector<string> >()) //遍历选项值
{ cout << str << ","; }
cout << endl;
}
if (vm.count("depth"))
{ cout << "depth opt:" << vm["depth"].as<int>() << endl;} //处理搜索深度
}
void case1(int argc, char* argv[])
{
options_description opts("demo options");
string filename;
opts.add_options()
("help,h", "help message\n a bit of long text")
("filename,f",
value<string>(&filename)->default_value("test"), "to find a file")
("dir,D", value<vector<string> >()->multitoken(), "search dir")
("depth,d", value<int>()->implicit_value(5), "search depth")
;
variables_map vm;
store(parse_command_line(argc, argv, opts), vm);
notify(vm);
print_vm(opts, vm);
stringstream ss;
ss << "filename=a.cpp\ndir=/usr/bin\ndepth=10";
store(parse_config_file(ss, opts), vm);
ifstream ifs("config.ini");
store(parse_config_file(ifs, opts, true), vm);
const char *str = "config.ini";
store(parse_config_file<char>(str, opts, true), vm);
}
int main(int argc, char* argv[]) //需要命令行参数
{
case1(argc, argv);
}
#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;
#include <boost/program_options.hpp>
using namespace boost::program_options;
//
int case1(int argc, char* argv[])
{
options_description opts("demo options");
opts.add_options()
("help", "just a help info")
("filename", value<string>(), "to find a file")
;
variables_map vm;
store(parse_command_line(argc, argv, opts), vm);
if (vm.count("help"))
{
cout << opts << endl;
return 0;
}
if (vm.count("filename"))
{ cout << "find " << vm["filename"].as<string>() << endl;}
if (vm.empty())
{ cout << "no options" << endl; }
return 0;
}
//
void case2()
{
value<string>();
value<int>()->default_value(10)
->implicit_value(1);
double x;
value<double>(&x)->zero_tokens()
->multitoken()->required();
}
//
void print_vm(options_description &opts, variables_map &vm)
{
if (vm.empty())
{
cout << opts << endl;
return;
}
if (vm.count("help"))
{
cout << opts << endl;
}
//输出查找文件名,因为它有缺省值,故总存在
cout << "find opt:" << vm["filename"].as<string>() << endl;
if (vm.count("dir"))
{
cout << "dir opt:";
for(auto& str:
vm["dir"].as<vector<string> >())
{ cout << str << ","; }
cout << endl;
}
if (vm.count("depth"))
{ cout << "depth opt:" << vm["depth"].as<int>() << endl;}
}
void case3(int argc, char* argv[])
{
options_description opts("demo options");
string filename;
opts.add_options()
("help,h", "help message\n a bit of long text")
("filename,f",
value<string>(&filename)->default_value("test"), "to find a file")
("dir,D", value<vector<string> >()->multitoken(), "search dir")
("depth,d", value<int>()->implicit_value(5), "search depth")
;
variables_map vm;
store(parse_command_line(argc, argv, opts), vm);
notify(vm);
print_vm(opts, vm);
stringstream ss;
ss << "filename=a.cpp\ndir=/usr/bin\ndepth=10";
store(parse_config_file(ss, opts), vm);
ifstream ifs("config.ini");
store(parse_config_file(ifs, opts, true), vm);
const char *str = "config.ini";
store(parse_config_file<char>(str, opts, true), vm);
}
//
void case4(int argc, char* argv[])
{
options_description opts("demo options");
string filename;
opts.add_options()
("help,h", "help message\n a bit of long text")
("filename,f",
value<string>(&filename)->default_value("test"), "to find a file")
("dir,D", value<vector<string> >()->multitoken(), "search dir")
("depth,d", value<int>()->implicit_value(5), "search depth")
;
variables_map vm;
positional_options_description pod;
pod.add("filename", 1).add("dir", 2).add("depth", -1);
auto pr =
command_line_parser(argc, argv).
options(opts).
positional(pod).
run();
store(pr, vm );
notify(vm);
print_vm(opts, vm);
}
//
string name_mapper(const string& env_name)
{
static map<string, string> nm =
{{"HOME", "home"},{"USER", "uname"}};
return nm[env_name];
}
void case5(int argc, char* argv[])
{
options_description opts("demo options");
string filename;
opts.add_options()
("help,h", "help message\n a bit of long text")
("filename,f",
value<string>(&filename)->default_value("test"), "to find a file")
("dir,D", value<vector<string> >()->multitoken(), "search dir")
("depth,d", value<int>()->implicit_value(5), "search depth")
("home", value<string>(), "home dir")
("uname", value<string>(), "user's name")
;
variables_map vm;
store(parse_environment(opts, name_mapper),vm);
cout << vm["home"].as<string> ()<< endl;
cout << vm["uname"].as<string> ()<< endl;
notify(vm);
print_vm(opts, vm);
}
//
void case6(int argc, char* argv[])
{
options_description opts1("group 1");
opts1.add_options()
("help,h", "help message");
options_description opts2("group 2(hide)");
opts2.add_options()
("filename,f", value<string>(), "to find a file");
options_description opts3("group 3");
opts3.add_options()
("dir,D", value<vector<string> >()->composing(), "search dir")
("depth,d", value<int>(), "search depth");
options_description opts_all;
opts_all.add(opts1).add(opts2).add(opts3);
options_description opts_cfgfile;
opts_cfgfile.add(opts2).add(opts3);
options_description opts_showhelp("demo options");
opts_showhelp.add(opts1).add(opts3);
variables_map vm;
store(parse_command_line(argc, argv, opts_all), vm);
store(parse_config_file<char>("config.ini", opts_cfgfile, true), vm);
if (vm.count("help") || vm.empty())
{
cout << opts_showhelp << endl;
return;
}
notify(vm);
print_vm(opts_all, vm);
}
//
int main(int argc, char* argv[])
{
//case1(argc, argv);
case2();
//case3(argc, argv);
//case4(argc, argv);
//case5(argc, argv);
case6(argc, argv);
}