10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ のソースに twenty one と書いたら 21 になるようにする

Last updated at Posted at 2014-08-24

が面白かったので書いてみた。

目的は、

  • onetwenty one をソースコードに直接書けるようにすること。
  • twenty one / three21/3 と解釈すること。

辺り。

念の為に書いておくと、何の役にも立たない。

version 1 -- operator()

c++
#include <iostream>

struct numbase
{
  int m;
  numbase( int m_ ): m(m_){}
  int value() const {  return m;  }
  virtual ~numbase(){}
};

struct num : public numbase
{
  num( int m_ ): numbase(m_){}
};

struct ten : public numbase
{
  ten( int m_ ): numbase(m_){}
  num operator()( num const & n ) const {  return num( m+n.value() ); }
};

std::ostream &
operator<<( std::ostream & o, numbase const & x )
{
  return o<<x.value();
}

int operator/( numbase const & a,  numbase const & b )
{
  return a.value() / b.value();
}

#define one (num(1))
#define two (num(2))
#define four (num(4))
#define twenty (ten(20))
#define fourty (ten(40))

int main()
{
  std::cout << one << std::endl;
  std::cout << fourty / two << std::endl;
  std::cout << fourty four / two << std::endl;
  std::cout << fourty four / twenty two << std::endl;
}

こんな感じ。

  • 演算子を定義すれば、四則演算可能。
  • fourtyfourty four もOK。
  • one hundred twenty four とかも行けそうだけど、面倒なので書いていない。
  • printf には対応していない。

特に、printf に対応するのはすごく難しいと思う。
別の printfを用意して、マクロでそちらに回してしまうという作戦なら可能だけど。

version 2 -- operator""

合法的に printf に渡したいと考えていて、別の案を思いついた。
こちらのほうがシンプル。

c++
// clang++ -std=c++11 -Wall
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <typeinfo>

inline int
operator"" _eng(char const* s, std::size_t size) {
  int sum=0;
  for( auto it = s ; it != s+size ; ++it ){
    if ( it==s || it[-1]==',' ){
      sum+=atoi(it);
    }
  }
  return sum;
}

#define one "1"_eng
#define two "2"_eng
#define three "3"_eng
#define four "4"_eng
#define twenty "20,"_eng
#define thirty "30,"_eng
#define fourty "40,"_eng
#define hundred "00,"_eng

int main()
{
  std::printf( "%d %d %d %d\n", one, fourty, fourty four, fourty four / twenty two );
  std::cout << one << std::endl;
  std::cout << fourty / two << std::endl;
  std::cout << fourty four / two << std::endl;
  std::cout << fourty four / twenty two << std::endl;
  std::cout << four hundred << std::endl;
  std::cout << two hundred one << std::endl;
  std::cout << one hundred twenty two << std::endl;
  std::cout << ( typeid( fourty four )==typeid(int) ? "int" : "NOT int" ) << std::endl; // => int 
}

最初からこうすればよかった。

  • 演算子を定義すれば、四則演算可能。
  • fourtyfourty four もOK。
  • one hundred twenty four もOK。
  • printf にも合法的に対応。

ユーザー定義リテラルにも文字列の連接が使えることを利用した。

10
10
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
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?