が面白かったので書いてみた。
目的は、
-
one
やtwenty one
をソースコードに直接書けるようにすること。 -
twenty one / three
を21/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;
}
こんな感じ。
- 演算子を定義すれば、四則演算可能。
-
fourty
もfourty 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
}
最初からこうすればよかった。
- 演算子を定義すれば、四則演算可能。
-
fourty
もfourty four
もOK。 -
one hundred twenty four
もOK。 -
printf
にも合法的に対応。
ユーザー定義リテラルにも文字列の連接が使えることを利用した。