優先順位付オーバーロード関数オブジェクト

事の起こり
apply(a,b)(  //a,bは多態型
  [](int,int){}
  ,[](auto,int){}
  ,[](auto,auto){}
)

みたいなことをやりたかった

優先順位付オーバーロード関数オブジェクト

関数が上からチェックされるオーバーロード関数オブジェクト
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

ordered overload function oject · GitHub

    auto f=alol::make_poly(
        [](int,auto){std::cout<<"(int,auto)";}
        ,[](auto,int){std::cout<<"(auto,int)";}
        ,[](auto,auto){std::cout<<"(auto,auto)";}
    );
    f(42,42);


上から評価されるので(int,auto)と(auto,int)でかち合わない

問題は

    auto g=alol::make_poly(
        [](double){std::cout<<"double";}
        ,[](int){std::cout<<"int";}
    );
    g(42);

のようなときにintがdoubleに暗黙型変換されてしまうことである
そういう場合はoverloadルールで解決されるmake_overloadを使おう
make_overloadを書いた - ここは匣

だらよ/だらよ3※の感想の様な

自転車創業さんの
そう、あたしたちはこんなにも理不尽な世界に生きているのだらよ」(以下だらよ)
そう、あたしたちはこんなにも理不尽な世界に生きているのだらよ3 ※この世界で2の発売予定はありません。」(以下だらよ3※)
の感想、のような。のような
私は普段、感想とか感想とかを書くタイプの人類ではないのですが、ちょっと成仏してもらわないと困る訳で、出力して行こうかと思いました訳で。



当然ですがネタバレを含みます
未プレイの良い子は今すぐamazonとかさんげっとに行って買ってくるんだ。前作未プレイならそっちも買ってくるんだ。ロストカラーズメロンブックスで買うのがお勧めだ。

続きを読む

constexpr variantの限界:自分版

Variant
型安全Union
関数型風にいうと直和型
例えば

 Variant<int,double,string> 

であればint,double,stringの内どれかの値が入っている
複数の型のうちの一つを入れることができる型

variantはとても便利な機能だ。C++の標準にもこれと似たものを入れようという動きがある。それだけこの機能が求められているということであろう

それだけ求められているvariantである。やはりconstexprに対応させたい。させるべきである。そう考えるのは人間の道理である。

melpon.org


しかしこのクラスにはoperator=が実装されていない。実装できなかったのだ

variant a(3),b(string("ABC"));
a=b;

このような時、プログラムはどのように動くべきであろうか
何らかの方法で3の値を安全に破棄し、『何らかの方法でstring()を構築して』ABCを代入する
と言ったところであろう
実行時であればplacement newを用いて3があったメモリ上にstringを構築するであろう
しかし、それはコンパイル時にはできないことなのだ。コンパイル時にnewを行うことはできない
故にstringを構築できず、故にoperator=を実装することができないのである


故に、完全なconstexpr variantを作ることができなかったのである。私は

さぁ、私でないあなた。今すぐC++を立ち上げよう。この問題を解決しよう

2^n - 1 を素因数分解した結果一覧

http://melpon.org/wandbox/permlink/UPjHWBam24a75P9U

2^1-1 ,3
2^2-1 ,7
2^3-1 ,3,5
2^4-1 ,31
2^5-1 ,3,3,7
2^6-1 ,127
2^7-1 ,3,5,17
2^8-1 ,7,73
2^9-1 ,3,11,31
2^10-1 ,23,89
2^11-1 ,3,3,5,7,13
2^12-1 ,8191
2^13-1 ,3,43,127
2^14-1 ,7,31,151
2^15-1 ,3,5,17,257
2^16-1 ,131071
2^17-1 ,3,3,3,7,19,73
2^18-1 ,524287
2^19-1 ,3,5,5,11,31,41
2^20-1 ,7,7,127,337
2^21-1 ,3,23,89,683
2^22-1 ,47,178481
2^23-1 ,3,3,5,7,13,17,241
2^24-1 ,31,601,1801
2^25-1 ,3,2731,8191
2^26-1 ,7,73,262657
2^27-1 ,3,5,29,43,113,127
2^28-1 ,233,1103,2089
2^29-1 ,3,3,7,11,31,151,331
2^30-1 ,2147483647
2^31-1 ,3,5,17,257,65537
2^32-1 ,7,23,89,599479
2^33-1 ,3,43691,131071
2^34-1 ,31,71,127,122921
2^35-1 ,3,3,3,5,7,13,19,37,73,109
2^36-1 ,223,616318177
2^37-1 ,3,174763,524287
2^38-1 ,7,79,8191,121369
2^39-1 ,3,5,5,11,17,31,41,61681
2^40-1 ,13367,164511353
2^41-1 ,3,3,7,7,43,127,337,5419
2^42-1 ,431,9719,2099863
2^43-1 ,3,5,23,89,397,683,2113
2^44-1 ,7,31,73,151,631,23311
2^45-1 ,3,47,178481,2796203
2^46-1 ,2351,4513,13264529
2^47-1 ,3,3,5,7,13,17,97,241,257,673

mod [2^n - 1] は(比較的)高速に計算することができる
mod [2^n + 1]も何となく高速に計算できそうな気がするんだけれどとくに方法が思いつかない

stateful constexpr Counter/CompiletimeTypeID

stateful constexprとは?という問題についてはまずこの辺りを見ていただきたい
C++のconstexprは参照透明とは限らない - 魂をC++に捧げよ
本の虫: constexprで非定数式の状態を保持

このように書かれるたびに(≠呼び出されるたび)違う値を返すconstexpr関数を実装することができる
これが本当にconstexprなのか?といわれると怪しいが

元の記事では32から0までflagが立てられているものを探していく、という実装である
しかし、この実装では当然32以上のものは作れないので1から数え上げていく方法に変えた
ついでにTypeIDを実装した
これによりUnique関数のオーダーがO(NlogN)に下がるだろう
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ



無限ループをオーバーロードで無限ループをはじいている

現状の方式の問題点

・何かとO(N)であること
next()関数はO(N)時間かかる関数でありあまり効率的ではない
また、constexprの再起制限も気になるところだ。C++11の悪夢再び
再起制限のほうは何とかなるような気もするが、検索オーダーを下げると折角減らしたwarningがまた増えるような気がする

GCCでwarningが消えきらない
ライブラリがwarningを吐くのは当然いいことではない

非constexpr文脈内でconstexpr関数をコンパイル時評価したような気分になる方法

どうやら本日学生生活最終日らしいです。不思議

std::cout<<log(42);

このような場合logがconstexpr関数であってもコンパイル時に評価されない
constexpr関数はconstexprな文脈でのみ呼び出されからだ。上記はconstexpr文脈ではない


よってlogをコンパイル時に評価したい場合constexprな文脈で呼び出す必要がある
例えば以下の通りだ

constexpr auto a=log(42);//コンパイル時に処理される
std::cout<<a;

このプログラムは以下と同等に動くことが期待される

std::cout<<3.73767;

しかしこれはだるい。なのでこんなマクロを作ってみた


#define MACRO(expr) ([]{constexpr auto a=(expr);return a;}())

これを使うとconstexpr呼び出ししたような気分になれる。気分?気分

以下のようになるはずだ

std::cout<<MACRO(log(42));

std::cout<<[]{constexpr auto a=log(42);return a;}();
std::cout<<[]{return 3.73767;}();

最後は関数がinline展開されて

std::cout<<3.73767;

となるはずだ。コンパイラの最適化が十分に働いてくれれば


[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
この場合だとマクロを使わずベタに書いている場合0.75秒かかっているのに対し
マクロ版は0.09秒で計算を終えている


ただし、コンパイラ最適化を強くした場合
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
両者ほとんど変わらない数値を出している。人生大体コンパイラがどうにかしてくれる。コンパイラに母性を求める日も近い

C++コードを投げるとアセンブラを投げ返すハイテックなオンラインサービス

最近聞いたいい話
Compiler Explorer
タイトルの通りC++のコードを打ち込むとアセンブラで返してくれる

ちなみにそのままC++11/14なコードを打ってもコンパイルエラーとなる
コンパイラオプションは適当に[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッとかから必要そうなところを切り抜いてもってこよう

ところでこういうサービスもオンラインコンパイラと呼んでいいのだろうか

  • std=gnu++1y -O2 -march=native



yoh on Twitter: "@Fuyutsubaki http://t.co/F4iRJPPev9 こういうのがありますよ。"