LoginSignup
3
2

More than 5 years have passed since last update.

クラス内の一部メソッドを特殊化した例

Last updated at Posted at 2015-07-07

はじめに

引数(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でハイライティングできるんですね.便利ですね.

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2