はじめに
引数(argc, argv)の中身を効率よく取り出すために,Argumentクラスというのをつくっていました.その中で必要だったのは,"-i 20"のように,ある文字列("-i") のあとに続く数字("20")や文字列を任意の型でとってこられるようなメソッドでした.これは, int Argument::get_int(std::string)
のような関数をそれぞれの型に対して定義すればできますが,それぞれ用意しないといけないのが面倒です.できれば, int a = arg.get<int>("-a");
のような記述でできれば良いのですが,テンプレートの書き方が少々面倒くさいです.先日(2,3年ほど前)に調べてわかったことを,以下にまとめました.
サンプルコード
以下のコードは,擬似的な引数解析プログラムです.簡単のためコンパイルで引数がいらないように書いています.標準ライブラリのみで作成しているため,コピペでコンパイル可能です.Argument::get()関数が例です.
example.cpp
#include <string>
#include <iostream>
#include <vector>
#include <cstdlib>
// 文字列strをそれぞれの型に変換する.
template <typename T> T convert ( const std::string& str );
template<>
std::string convert ( const std::string& str )
{
return str;
}
template<>
int convert ( const std::string& str )
{
return std::atoi ( str.c_str() );
}
template<>
double convert ( const std::string& str )
{
return std::atof ( str.c_str() );
}
// 擬似引数処理クラス
class Argument
{
private:
std::vector<std::string> args_;
public:
Argument ( void );
~Argument ( void );
void add ( const std::string& str ) ;
int size ( void ) const;
template <typename T> T get ( const int i ) const;
};
Argument::Argument ( void )
{
return;
}
Argument::~Argument ( void )
{
return;
}
void
Argument::add ( const std::string& str )
{
this->args_.push_back ( str );
}
int
Argument::size ( void ) const
{
return static_cast<int> ( this->args_.size() );
}
template <typename T>
T
Argument::get ( const int i ) const
{
if ( this->size() <= i ) return T();
return convert<T> ( this->args_.at ( i ) );
}
// template int Argument::get<int> ( const int idx ) const; と書けばok.
// 以下はマクロを使って,手間を省いたもの
#define ARGUMENT_GET(TYPE) template TYPE Argument::get<TYPE> ( const int idx ) const
ARGUMENT_GET ( std::string );
ARGUMENT_GET ( int );
ARGUMENT_GET ( double );
int main ( int argc, char** argv )
{
Argument arg;
arg.add ( "abc" );
arg.add ( "10" );
arg.add ( "1.2" );
std::string str = arg.get<std::string> ( 0 );
int a = arg.get<int> ( 1 );
double b = arg.get<double> ( 2 );
std::cerr << str << " " << a << " " << b << std::endl;
return 0;
}
実行例
$ ./a.out
abc 10 1.2
$
書いてて気づいたのですが,bashでハイライティングできるんですね.便利ですね.