2016-07-29

東京都知事選挙の候補者の主張の実現可能性の考察

現在、都知事選挙が行われている[要出典]。筆者の手元には、東京都選挙管理委員会の発行した、「東京都知事選挙 選挙公報」と題された新聞様の文書がある。この選挙公報は、「立候補者21名のうち掲載申請があった20名から提出された原稿をそのまま製版の上掲載」しているという。

この選挙公報をつらつら眺めていると、多くの立候補者の主張する公約の実現には、極めて超法規的な権力(既存の国際条約、憲法、法律、条例への違反)、日本の単年度国家予算(一般会計と特別会計を合わせて重複を省いた額、だいたい200兆円ほど)を超える金、時には物理法則を捻じ曲げる必要があることに気がついた。

しかし、それでもなお、公約を真面目に実現させた場合の状況を想像すると、なかなかにユーモラスな結果となることが予想される。そこで、この記事では、今回の都知事選挙の立候補者が選挙公報に寄せた内容を公約とみなし、文字通り実現させることが可能か、そして文字通り実現させた場合に起こるユーモラスな結果を考察したい。

今回の考察にあたっては、通常の常識における制約は考慮しない。都知事には超法規的な権力が与えられ、都知事の意思ひとつで、すべての日本国が批准する国際条約からは脱退できるものとし、日本の憲法、法律、条例は変更可能とする。すべての日本国民は、さながら大躍進政策や文化大革命のごとく、都知事の計画経済にしたがって行動するものとする。あらゆる倫理、道徳より都知事の意思が優先するものとする。

ただし、最低限の制約は必要である。そこで、物理法則に違反する内容(例:永久機関)は不可能とする。また、日本の単年度国家予算(約200兆円)を超える金が必要な内容は条件付き実現可能とする。日本国外に対する内容には通常の常識を適用する。

考察する立候補者の順番は、選挙公報の順番であり、他意はない。

立花考志

この立候補者の公約は全て実現可能である。

この立候補者の主張は、東京都の条例によってMHK集金人の戸別訪問を規制するとか、放送法の改正によってNHKの受信料を支払わなくてもよくするといったたぐいのことである。今回の考察における大胆な制約の下では、NHK自体を消失させることも可能であるので、この程度のことは、他の立候補者の主張に比べれば、比較的簡単に実現可能である。

マック赤坂

この立候補者の公約は条件付き実現可能である。実現可能性は、現在の条件に依存する。

この立候補者の公約の多くは、金さえあれば実現可能である。例えば、「待機児童ゼロ、老人介護施設3倍増」とか、「中学生以下65才以上に3万円支給」とか、「東京全域バリアフリー化」などといった公約は、日本の国家予算の範囲内の金で実現できる。

また、抗うつ薬の使用禁止とか精神科医の免許取り消しなどといった公約も、法律を改正すれば容易に可能である。

「東京オリンピックを大成功させる」という公約には、日本国外の人間の動員も必要であるが、オリンピックは世界的に有名なイベントであるから、日本国内さえ十分に整備して全国民を強制徴用して動員すれば大成功は可能であろう。

ただし、疑問点はある。

「都職員に・・・能力給・信賞必罰を徹底し人員の20%カットを目指す」という内容は、論理的に成り立たない可能性がある。現在の都職員の20%以上が本来不要であるならば可能である。しかし、もし不要な都職員が20%未満であれば、彼は不要でもないのに不当に解雇される。これは信賞必罰と矛盾する。したがって、この立候補者の公約が実現可能かどうかは、現在の都職員の20%以上が不要であるかどうかにかかっている。

「スマイルあふれる東京」を実現するには、東京にいる人間に強力な抗うつ剤、あるいは筋弛緩剤(顔面を弛緩させることにより笑っているような表情にする)の摂取を義務付けるなどして、強制的にスマイルを発生させなければならない。公約では同時に抗うつ剤の禁止を主張しているので、例えば亜酸化窒素のような顔面の筋肉を弛緩させる薬品を使うのであろう。極めてディストピアな世界になるが、もちろん実現可能だ。

また、「都内のレストランにチップ制を導入」とある。日本ではチップの文化がないので、これを導入するには大躍進や文化大革命のごとき都民の強制徴用と動員が必要になる。

総合的に判断して、この立候補者の公約は、疑問点がいくつかありながらも、実現可能である。

鳥越俊太郎

この立候補者の公約は実現不可能である。

この立候補者の公約の多くは、金さえあれば実現可能である。必要な金は国家予算を超えないので実現可能である。

がん検診の促進や骨粗しょう症対策は、通常の常識の範囲内でも実現可能であるし、災害に強い東京も、金さえあれば実現可能である。

ただし疑問点はある。「希望するすべての人が正社員になれる格差のない社会をつくり」とあるが、これは難しい。ここでいう「正社員」とは労働基準法等に基づく被雇用者であって、かつ、有期契約労働者や派遣労働者や請負ではなく、仕事を依頼する人間が直接、期間を限定せず、雇用するものをいうのであろう。

これは、雇用された会社ではなく、常に客先に常駐している派遣をなくすのであれば、通常の常識の範囲内ではあるが、「希望するすべての人」という条件により、通常の常識からは外れてしまう。

例えば、筆者の自宅の壁付けコンセントが破損したとする。コンセントの修理には電気工事士の資格が必要である。筆者は同資格を保有していないので、資格保有者に修理を依頼する。もし、資格保有者が正社員を希望した場合、筆者は資格保有者を雇用しなければならない。もちろん、有期雇用契約ではなく無期雇用契約でなければならない。

これを実現するには、人を雇用する手間を極端に下げなければならない。例えば、役所に印鑑証明でも出しに行く程度の気軽さで、雇用契約を結べるよう、行政の手厚いサポートが必要だ。雇用の概念も大幅に変わるだろう。この公約が実現した社会では、都民ひとりひとりが大勢の人間を相互に雇用しあっている状態になる。もはや現在の「正社員」などどうでも良くなっているはずだ。しかし、実現可能ではある。

「職人を大切にするマイスター制度を拡充します」と書いてある。「拡充」とは大辞林 第三版の解説によれば、「設備・組織などをひろげ,充実させること」である。すると、都知事選前にすでに日本にマイスター制度が存在しなければならない。現在、日本にはマイスター制度は存在していないので、この公約は前提となる条件を欠き実現不可能である。

「できるだけコンパクトでシンプルな2020オリンピック」と書いてある。オリンピックは大規模なイベントであり、コンパクトではないので実現不可能である。今回の考察では、多額の金を費やすことにより実現可能なことは実現可能だと判定するが、実現には多額の金がかかるにもかかわらず金をかけずに実現するという矛盾した公約は実現不可能だと判定する。

増田ひろや

この立候補者の公約はすべて実現可能である。

この立候補者の公約の多くは、金さえあれば実現可能である。必要な金は国家予算を超えないので実現可能である。

例えば、子育てや介護福祉や女性の活躍の場の充実などは、金があれば実現可能である。災害対策として上げている木造住宅の不燃化、耐震化も、金があれば実現可能である。オリンピックの成功や、その後も成長を続けるなども、金があれば実現可能である。

ただし疑問点がある。

「都民が、あたたかさにあふれ、不安がなく、安心して生活できる環境・社会の実現を目指します」とある。

「あたたかさにあふれ」るためには、暖房を完備しなければならない。冬の屋外でも「あたたかさにあふれ」るためには、屋外に隙間なく暖房器具を配置するか、すべて屋内にしてしまう必要がある。すべてを屋内にした場合、東京都民はドーム型通路の中を歩いて移動することになる。これは、金さえあれば可能だ。

「不安がなく」なるためには、全都民に強力な抗うつ剤の摂取を義務付けなければならない。極めてディストピアな世界となるが、もちろん実現可能だ。

桜井誠

この立候補者の公約は実現不可能である。

この立候補者の公約の多くは、倫理、道徳さえ無視すれば実現可能である。

倫理上問題のある外国人生活保護の廃止、表現の自由を侵害する半日ヘイトスピーチ禁止条例制定などは、今回の考察の制約の範囲内で実現可能である。

実現不可能なのは、「コンパクトな東京五輪の実施」だ。オリンピックは大規模なイベントでありコンパクトではないので実現不可能である。今回の考察では、多額の金を費やすことにより実現可能なことは実現可能だと判定するが、実現には多額の金がかかるにもかかわらず金をかけずに実現するという矛盾した公約は実現不可能だと判定する。

今尾貞夫

この立候補者の公約はすべて実現可能である。

この立候補者の公約の多くは、金さえあれば実現可能である。

子育て、教育にかかる個人負担はないとか、幼稚園、保育園は誕生直後から全員受け入れ態勢を取るとか、老人介護のために食堂浴場を整備した家を作るなどは、国家予算以下の額の金で実現可能である。

実現可能ではあるが疑問のあるものとして、直接民主制の導入を主張していることだ。

「知事交代をチャンスに都民皆の希望を集約、生活不安解消策を皆で見出し、皆で実現していく皆の参加する都政に変えます。」

皆が参加する都政を実現するためには、選挙で代表者を選出するのではなく、都民皆が議会に参加できる必要がある。したがって、この公約を実現するには直接民主制に切り替える必要がある。

谷山ゆうじろう

この立候補者の公約は条件付き実現可能である。実現可能性は、国外の未来の条件に依存する。

この立候補者の公約の多くは、実現可能である。

ただし、国外の未来の条件に依存した公約がある。

「「DONALD TRUMP アメリカ大統領」に毅然とNO」と書いてある。2016年アメリカ合衆国大統領選挙において、ドナルド・トランプは立候補者の一人であり、大統領になる可能性があるが、大統領選挙は2016年11月8日に行われ、投票結果が正式に発表されるのは2017年1月とされている。したがって、ドナルド・トランプが今回、あるいは将来のアメリカ合衆国の大統領になるかはまだ未定であり、もしドナルド・トランプが大統領にならなかった場合、大統領ではないので、前提となる条件を欠き、「毅然とNO」と言うこともできない。

今回は選挙公報の実現可能性だけを考察するものであって、その内容の良し悪しについて考察はしない。しかし、この立候補者の選挙公報の日本語は、解釈が難しい。例えば、以下は選挙公報からの抜粋である。

2020年世界はTOKYOに

その中心地、国立競技場からのみ発信します

イギリスBBC、中東アルジャジーラTVなど世界を舞台に活動してきた谷山ゆうじろう
は、毎日英語で定例記者会見を行いNHKワールドで生中継。日本を売り込みます

TOKYOから国際化&自立国家

国際人を育む、夢のあるカラーフルなシティTOKYOを目指す

既成政党の組織票・お金ありきの選挙戦に、断固反対します。名前を連呼するだけの選挙カーなし、
事務所なし、ガソリン代なし。あるのは国家観と、iPhoneのみ。従来の思考回路ではもう日本は
進化できません。毎年2万人人口減少の高齢化の中で、若い人に夢を。移動中のスマホで、ご家庭
のPCで、2020東京オリンピックスタジアム(建設中)前からの生放送演説をぜひお聞きください。

これは一部だが、とにかく文章らしい文章がない。「iPHoneのみ。」とか、「若い人に夢を。」とか、よくわからない文章の区切り方と構成をしている。筆者の解釈によれば、この立候補者は、

  • 2020年に国立競技場から発信(生放送演説?)をする
  • 発信は国立競技場からしか行わない
  • 東京オリンピックスタジアムでも生放送演説(発信ではない?)を行う
  • 演説の際、東京オリンピックスタジアムはまだ建設中である(生放送演説は2020年ではない?)
  • 事務所もガソリン代もない

などの情報が得られたが、この日本語の解釈が正しいのかどうか、筆者には自信がない。発信と生放送演説は違うことと、生放送演説は2020年ではなさそうなので、記述は矛盾しないように読める。この立候補者の文章の日本語は極めて解釈が難しいため、今回の実現可能性の考察は完全に間違っている解釈に対して行っている可能性がある。

後藤輝樹

この立候補者の公約は条件付き実現可能である。公約は国家予算を超える金があれば実現可能である。

この立候補者の選挙公報は、ほとんどが公約の箇条書きで構成されている。立候補者の学歴や職歴、属する政党などの公約ではない情報は極めて少ない。

この立候補者の公約をすべて実現するには、日本の国家予算を超える金が必要になる。したがって、この立候補者の公約は条件付き実現可能と判断した。

特に金のかかる公約は以下の通り

「すべての低所得者(国民)に毎月8万円支給します(ベーシックインカム導入)」

最大で以下の額の金がかかる。

$$ 8万円 \times 12ヶ月 \times 1億2千万人= 115兆2000億円 $$

「日本の借金約1000兆円を10分の1以下に減らし」などは、デノミネーションを行えば額面上は実現可能である。

「核武装します」、これには多額のカネがかかる。

「日本の食料自給率およびエネルギー自給率100%以上を目指します」

以下の公約は物理法則に違反しない。

「地震、津波および気象兵器テロ(人工地震兵器等)対策をします」

人間が知覚可能な地震を人工的に起こすことは可能であり、津波や降雨、旱魃なども、ある程度人工的に操作可能である。またこれは兵器開発ではなく対策なので、そのような兵器が存在しなくても実現可能である。

また、この立候補者は、日本の政治を天皇を元首とする君主制政治に変更する公約をしている。

公約は多数あるが、お互いに矛盾する公約は見つけられなかった。

「東京五輪中止、または超低コストでやります。」と書いてある。金があれば実現可能なことは多いが、支出を削るのに金は使えないので実現は難しいが、中止は可能なので実現可能だ。

中川ちょうぞう

この立候補者の公約は条件付き実現可能である。公約の実現には国家予算を超える金が必要になる。

この立候補者の選挙公報は具体性にかけるが、すべての実現を考えると、おそらく国家予算を上回る額の金が必要になる。

高橋しょうご

この立候補者の公約はすべて実現可能である。

この立候補者の公約をすべて実現するには、国家予算以下の金で足りる。

公約には具体的な対応作に欠けるものが多い。

「少子化対策の公約が守られていたら、私達の回りには今より多くの子供達がいたはずです」という文章があるが、これは誤りである。なぜならば、公約の少子化対策が効果のないものであれば、たとえ公約が守られていたとしても児童人口は増加しない。

せきくち安弘

この立候補者の公約は、全て実現可能である。

この立候補者は憲法改正を公約としている。その他の公約も国家予算以下の金で実現可能である。

この立候補者の提案する日本国憲法の前文には、「国民が投票により選ぶ代表が、常時一カ所に集う新しい国際協調の仕組みとして世界最高会議体(仮地球議事堂)を形成してゆく為に」という文章がある。これを解釈すると、おそらく政治家は24時間365日、一カ所に拘束されるのだろう。

山口敏夫

この立候補者の公約は、すべて実現可能である。

この立候補者の公約は、国家予算以下の金で実現できる。

「2020東京五輪・パラリンピックは・・・一、アスリート選手諸君の、”名誉”をかけた”活躍”に期待し、応援すること」と書いてあり、都民にオリンピック選手の応援を義務付けている。応援したくない都民がいたとしても、文化大革命、大躍進政策のごとく、都民の意思を無視して、都民徴用と強制応援を行えば実現可能となる。

やまなかまさあき

この立候補者の公約は、全て実現可能である。

「今立ち上がれ! 私達(眠れる子羊)よ!」と書いてあるが、都民は人間であり羊ではない。この文章は比喩であろう。しかし、眠れる獅子とか迷える子羊とはいうが、眠れる子羊とは何を意味するのであろうか。

「さあ、はじめよう«レジスタンス»!」とも書いてあるが、侵略や抑圧に対抗する民兵を組織して革命を目指すのではなく、同じく単なる比喩であろう。

「次代を担う!子供たちの輝ける未来«笑顔と笑い声のたえない»の創造を目指します!」と書いてある。「笑顔と笑い声のたえない」を創造するためには、都民に強力な抗うつ剤の摂取を義務付ける必要がある。ディストピアな社会になるが、もちろん実現可能だ。

岸本雅吉

この立候補者の公約は、全て実現可能である。

唯一気になるのが、徴農制だ。

「小学校・中学校時代に、「徴農制」を導入する」、「小学校・中学校時代に数期に分けて「徴農制」を導入します」

少し形は違うがポル・ポトを彷彿とさせる公約だ。

ないとうひさお

この立候補者の公約は、すべて実現可能である。

アメリカ合衆国のような自己責任について書いているが、それを実現するには修正第2条にある、「規律ある民兵は、自由な国家の安全にとって必要であるから、人民が武器を保有し、また携帯する権利は、これを侵してはならない。」のような、武装する権利を都民に認めるべきであるが、そのような言及はしていない。

また、「東京の人口を現在1/2にする」とも書いている。これは虐殺によって人口を減らすのではなく、地方に人を工場や企業を移転させることで実現するという。大躍進政策や文化大革命のような強制的な徴用と動員が必要であるが、もちろん実現可能だ。

望月義彦

この立候補者の公約は、全て実現可能である。

ゼロエミッション都市のために、緑化、木造、木質化を挙げている。おそらく厳しい建築規制が敷かれるのだろう。そのような厳しい建築規制では、東京の経済が他の公約どおりに「世界とともに成長し続ける未来都市」となれるかは疑問だが、十分な金さえあれば可能だろう。

また、「瞑想教育」を公約に入れているため、都民に特定の宗教を強制するものと見える。

小池ゆりこ

この立候補者の公約は、全て実現可能である。

ただし、実現した場合、社会構造を大きく変える公約がある。

「残業ゼロ」を実現するには、たとえ労使協定を結ぼうとも残業は違法になる法律を制定する必要がある。また、もちろん公務員も残業ができないので、国会議員の質問主意書の返答は極めて遅くなるだろう。

「満員電車ゼロ」を実現するためには、電車を拡張するより、東京都の経済を破壊するとか、都民を虐殺するなどしたほうが実現が容易だ。

「多摩格差ゼロ」もよくわからない公約だ。多摩を都心部のように経済的に充実させる公約であろうか。すると大躍進政策や文化大革命ばりに強制徴用と都民動員が必要になる。

宮崎正弘

この立候補者の公約は、全て実現可能である。

この立候補者の公約はあまりにも具体性に欠けるため、考察できることがほとんどない。

上杉隆

この立候補者の公約は、実現不可能である。

「知事給与ゼロ全額返上」と書いてあるが、給与返上は公職選挙法第199条の禁止する寄付にあたるので、現行法では禁止されているが、法律を改正すれば実現可能だ。

「首都直下型地震対策死者ゼロ」と書いてあるが、東京都で大規模な地震が起きた場合に死亡者を0人にできる保証はないので、実現不可能である。

「東京オリンピック運営費を当初のコンパクト案に」と書いてあるが、金さえあれば実現できることは多いが、支出を削るのは金がいくらあっても不可能なので、実現不可能である。

七海ひろこ

この立候補者の公約は、条件付き実現可能である。公約の実現可能性は国外の経済に依存する。

この立候補者は、「経済的にも精神的にも、世界一リッチな都市・東京を実現します」と書いている。これを実現するには、国外のすべての都市が東京の経済規模以下にならなければならない。国外に依存するので条件付き実現可能となる。

考察まとめ

金、法、倫理の制約を無視しても、これほど多くの立候補者の公約が実現不可能になるとは思わなかった。実現不可能な公約を出した立候補者は以下の通り。

マック赤坂、鳥越俊太郎、桜井誠、谷山ゆうじろう、後藤輝樹、中川ちょうぞう、上杉隆、七海ひろこ

以下は実現不可能な公約である。

オリンピックをコンパクトにする

オリンピックは巨大なイベントである。フルチンでかけっこをしていた昔と異なり、今のオリンピックは多数の国家から多数の選手が参加する。例えば、先のロンドン・オリンピックでは、204の国家から、10568人の選手が参加した。選手だけで1万人もいるのだから、これをどうやってコンパクトにせよというのか。参加国の桁を減らし、参加人数の桁も減らすしかない。しかし、おそらく立候補者はそこまでコンパクトにすることは考えていないだろう。

金をかければ実現できることは多いが、金をかけないことを実現するのは難しい。

実現可能性が過去や未来の不確定な結果に依存するもの

無能な都職員を20%クビにする公約を実現するには、現在の都職員の20%が実際に無能でなければならない。すでに確定した結果を変えることはできないので、現在の都職員のうち20%以上が無能でなければ実現できない。

マイスター制度を拡充するには、すでにマイスター制度が存在しなければならない。

ドナルド・トランプはまだアメリカ合衆国の大統領になることが確定していないので、もしドナルド・トランプが大統領にならなかった場合は、毅然とNOをいうこともできない。

日本の国家予算(約200兆円)を超える予算が必要になるもの

政治家は現在の国家予算という上限を認識すべきである。

2016-07-28

C++標準化委員会の文書: P0320R0-P0329R0

[PDF] P0320R0: Thread Constructor Attributes

pthread attributesに相当するstd::thread::attributesを追加する提案。これにより、移植性が高い方法でスレッドのスタックサイズや優先度などを設定できるようになる。

例えば、スタックサイズを指定するには以下のように書く。

std::thread::attributes attrs;
attrs.set_stack_size(4096*10);
std::thread t(attrs, func);

現在の提案ではスタックサイズの指定しか規定していないが、プラットフォームごとの設定も、thread::attributesを拡張することにより、自然な形で追加が可能だ。また、native_handleもサポートされているので、プラットフォームごとのコードも書きやすい。

WindowsのWin32 APIやインターフェースがだいぶ違うので、Windowsでこれを実装するのはすこし面倒だそうだ。

P0322R0: P0322r0 : exception_list

Parallelism TSにある並列実行中の例外をすべてexception_ptrで保持してくれるexception_listというライブラリは便利なのでParallelism TS専用にしておくのはもったいない。汎用的に使えるよう設計すべきだということでexception_listをユーザーが構築できるようにする提案。

exception_listはimmutableな設計になっている。

std::exception_list l ;
// push_back相当
l = std::exception_list( l, std::current_exception() ) ;

exception_listにはムーブがない。コピーはある。そのため、push_back相当のことするには、既存のexception_listのオブジェクトと追加するexception_ptrをコンストラクターに渡して新しいexception_listのオブジェクトを作る必要がある。

[PDF] P0323R0: A proposal to add a utility class to represent expected monad (Revision 2)

標準ライブラリにexpected<T,E>を入れる提案。optionalはexpected<T,bool>とみなすこともできる。さらに、expected<T,E>はvariant<T,E>の特殊なものとみなすこともできる。

expected<T,E>は、T型のオブジェクトかE型のオブジェクトのいずれか保持する。通常はT型のオブジェクトを保持し、エラー時にはE型のオブジェクトを保持している。

他の言語では、eitherという形で存在している機能だ。

P0324R0: One Concept Definition Syntax

関数コンセプトを廃止して変数コンセプトに一本化する提案。

// 関数コンセプト
template <typename T>
concept bool FC() {
    return constraint-expression;
}

// 変数コンセプト
template <typename T>
concept bool VC = constraint-expression;

問題は、現行のコンセプトTSはC++17に入らない見込みなので、あまり深く学ぶ意味がない。

P0325R1: Propose to adopt make_array into the IS

make_arrayを規格に入れる提案。

// std::array<int, 3>
auto a = std::make_array( 1, 2, 3 ) ;

便利だ。

[PDF] P0326R0: Structured binding: customization point issues

構造化束縛のcustomization pointはstd::tuple_sizeとstd::tuple_elementだったが、これは<utility>に依存する。utilityはfreestanding implementationではないので問題だ。そこで、構造化束縛のためのcunstomization pointを新たに作る。

関数の名前は、product_type_sizeとproduct_type_getになる。メンバー関数か、フリー関数として定義しておけば、range-based forのbegin/endに似たADL経由で見つけてくれる。

[PDF] P0327R0: Product types access

P0326と同じ提案だが、設計が少し違う。std::product_type::sizeとstd::product_type::getになっている。また型情報を得るためのtuple_element相当のstd::product_type::elementもある。

[PDF] P0329R0: Designated Initialization

C99にあるDesignated Initializationに似た機能。ただし省略ができない。


struct A { int a, b ; } ;

// すべてがdesignatorであるか、使わないかの二択
// C++: ill-formed
// C99: well-formed
A a = { 1, .b = 2 } ;

// designatorの順番は宣言順でなければならない。

// well-formed
A a = { .a = 1, .b = 2 } ;

// C++: ill-formed.
// C99: well-formed.
A a = { .b = 2, .a = 1 } ;

// designatorの重複は認められない
// C++: ill-formed.
// C99: well-formed 
A a = { .a = 1, .a = 1 } ;

// 配列の初期化はできない

// C++: ill-formed.
// C99: well-formed
A a = { [2] = 2 } 

// ネストはできない。
// C++: ill-formed.
// C99: well-formed.
A a= { .a.b.c.d = 0 } ; 

// リスト初期化はサポートしている
A a = { .a = { } } ;

目的はreadabilityを上げることのみ。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-27

C++標準化委員会の文書: P0310R--P0319R0

[PDF] P0310R0: Splitting node and array allocation in allocators

ノードメモリ確保を追加する提案。

listやmapといったリンクリストのデータ構造は、挿入コストがO(1)なのにもかかわらず、最近は敬遠されている。代わりに、挿入コストがO(N)であるunordered_mapが使われている。その理由は、メモリ断片化だ。

メモリ断片化を防ぐために、メモリを一括で確保して切り分けて返したり、解放されたメモリをリンクリストでpoolしておく、ノード専用のメモリ確保方法を、std::allocator_traitsに追加する提案。ノード専用のメモリ確保は、汎用的なpool allocatorよりも速いとしている。

Boost.Containerには同じ発想の実装があるが、C++03時代のstd::allocatorを使っていて、設計が古い。

P0311R0: A Unified Vision for Manipulating Tuple-like Objects

最近、tuple風オブジェクトとunpackingに関しての提案が多いので、そのまとめ。

tuple風オブジェクトとはtupleやpairやarrayのようなクラスや、あるいはアグリゲートのことだ。unpackingとは、構造化初期化のようなtuple風オブジェクトの要素を取り出す操作のことだ。

これ自体は特に新機能の提案をしていないが、tuple風オブジェクトに対するslicing操作が提供されるべきだとしている。例えば、先頭からN個だけunpackingするとか、先頭からN個目から残りをunpackingするとかだ。

[PDF] P0312R0: Make Pointers to Members Callable

メンバーへのポインターを関数呼び出しできるようにする提案。

メンバーへのポインターがメンバー関数を参照している場合、呼び出すのは面倒だ。

struct X
{
    void f() { }
} ;


int main()
{
    auto ptr = &X::f ;
    X x ;
    (x.*ptr)() ;
}

メンバーへのポインターは、クラスのオブジェクトを渡してやらなければならない。

現在、INVOKE(C++17ではstd::invokeとしてINVOKE要件を満たす呼び出し方をするテンプレート追加されている)で呼び出し可能なものは4つ。関数、関数ポインター、関数オブジェクト、メンバーへのポインターだ。

int arg ;
void func( int ) ;
auto func_ptr = &func ;

struct func_class
{
    void operator () ( int ) { } 
} ;

func_class func_obj ;
auto memptr = &func_class::operator() ;
 
func(arg) ; // 関数
func_ptr(arg) ; // 関数ポインター
func_obj(arg) ; // 関数オブジェクト
(func_obj.*memptr)(arg) ; // メンバーへのポインター

メンバーへのポインターだけ文法が違う。

従来、この文法の差異はライブラリで吸収していた。この提案では、普通に呼び出すことができるようにする。第一引数をクラスオブジェクトとみなす。

// (func_obj.*memptr)( arg )と同等
memptr( func_obj, arg ) ;

これはほしい。

P0313R0: Comparison operators in fold-expressions

fold式から比較演算子を消す提案。C++では、a < b < cのような式は慣習的な数学記法として期待される挙動をしない。そのため、fold式で比較演算子が使えても、メタプログラミングやDSL実装の役に立つだけだ。混乱を考えれば、消すほうが望ましい。

P0314R0: Querying the alignment of an object

alignofを式にも適用できるようにする変更。従来、alignofは型にしか適用できなかった。

int x = 0 ;

alignof(int) ; // OK
alignof(x) ; // エラー

この提案では、式にも適用できる。

int x = 0 ;
alignas (16) int y = 0 ;

alignof(x) ; // alignof(int)
alignof(y) ; // 16

[PDF] P0315R0: Lambdas in unevaluated context

Lambda式を未評価式の中でも使えるようにする提案。

従来、lambdaのoperator()はconstexprではなかったし、未評価式の中では使えなかった。その理由は、テンプレートに渡してSFINAEの文脈で考慮させることを禁止するためである。

もしlambdaがconstexprで未評価式の中で使えるとどうなるか。以下のようなコードが書けるようになる。

template < typename T, bool = []{
    T x ;
    T y = x ;
    auto iter = x.begin() ;
    auto end = x.end() ;
    iter != end ;
    *iter ;

    return true ;
}
>
void f()
{

}

これがSFINAEで考慮されるので、lambda式がconceptのように使えるようになってしまう。例えば、上のコードは、T型にデフォルトコンストラクターとコピーコンストラクターとデストラクターとbegin/endメンバー関数があるかどうか。begin/endの戻り値の型はコピーコンストラクターとデストラクター、operator !=とoperator *をサポートしているかどうかによって、SFINAEのルールによってテンプレートのsubstitutionを抑制できる。

問題は、そのような挙動をサポートするには、シグネチャにlambda式全体を含めなければならない。しかし、未評価式での使用を禁止しただけでは、迂回方法がまだある。そこで、エンティティのシグネチャに影響する使い方を直接禁止する文面が入った。

CWG_DEFECTS: C++ Standard Core Language Defect Reports and Accepted Issues

これにより、lambda式を未評価式で使うことを禁止する理由がなくなった。それゆえ、この提案では制限の緩和を提案している。

目的は、tupleなどの型シークエンスへの適用だ。

using sorted = decltype(sort(tuple, [](auto const& a, auto const& b) {
return std::integral_constant<bool, sizeof(a) < sizeof(b)>{};
}));

懸念していた問題が直接解決されたので、無用の制限は緩和すべきだ。

P0317R0: Directory Entry Caching

filesystemにディレクトリキャッシングを追加する提案。

ファイルシステムからディレクトリやファイルの一覧を取得する操作はコストが高いので、キャッシュしておきたい。しかし、下手なキャッシュは問題になる。

キャッシュ機能は、TS時にはあったが削られた。削る際、将来的に考察するとされていた。この提案はその考察である。

[PDF] P0318R0: decay_unwrap and unwrap_reference

decay_unwrapとunwrap_referenceの提案。

unwrap_reference_t<T>は、もしTがreference_wrapper<X>の場合、X &になる。decay_unwrap_t<T>は、もしdecay_t<T>の結果がreference_wrapper<X>の場合、X &になる。

つまり、reference_wrapperをunwrapするためのtraitsだ。reference_wrapperは標準ライブラリにおいて特別な扱いを受けていて、unwrapして扱う挙動になっているライブラリがいくつかある。それならば、標準でunwrapするtraitsが提供されているべきである。

[PDF] P0319R0: Adding Emplace functions for promise<T>/future<T>

future/promiseに対してemplaceを追加する提案。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-25

C++標準化委員会の文書: P0301R0-P0309R0

P0301R1: P0301R1: Wording for Unified Call Syntax (revision 1)

統一関数呼び出し記法

f(x,y)という式に対して、まずf(x,y)が妥当なフリー関数fを探し、見つからなければ、x.f(y)が妥当となるxのメンバー関数fを探す機能がまずひとつ。

この提案は、さらにUnified call introducer(統一呼び出し導入子)という文法により、メンバー関数呼び出しからフリー関数を呼び出す機能も提案している。

もともと、上の機能と同じ考え方で、x.f(y)という式に対してf(x,y)と同じ意味を持たせたかったが、様々な理由により没になった。そこで、既存の式とは異なる新しい文法を追加すればそのような機能が追加できるという発想で、unified call introducerの文法が追加された。その文法は.だ。

以下がunified call introducerを使った式となる。

.f(x,y)
.x.f(y)

行頭が.で始まっているが、これはtypoではない。これがunified call introducerだ。

.f(x,y)は、f(x,y)が妥当なフリー関数fの集合と、x.f(y)が妥当なメンバー関数fの集合からなる関数fの集合に対して、オーバーロード解決でbest viable functionを決定する。もともとの統一関数呼び出し記法が、f(x.y)でまずフリー関数を優先し、存在しなければメンバー関数を探しに行くのと違い、フリー関数、メンバー関数のすべてが等しく比較される。

.x.f(y)は、.f(x,y)と同じ意味である。

unified call introducerは、チェインイングをサポートしている。例えば以下のように書くと、

.x.f(y).g.(z)

以下と同じ意味になる。

.g( .f(x,y), z )

何故か。まず最初の.x.f(y)は、先に述べたように.f(x,y)と同じ意味になる。これをexprとする。残りは、.expr.g.(z)なので、これの意味は.g( .expr, z )となる。exprは.f(x,y)だったので、最終的には.g( .f(x,y), z )と同じ意味になる。

もはやアボミネーションと言ってもいいぐらい醜悪な何かになっている。こんなわかりにくい提案は入ってほしくない。

P0302R1: Removing Allocator Support in std::function (rev 1)

std::functionからアロケーターを取り除く提案。

std::functionのコンストラクターにはアロケーターを引数に取るものがあるが、その意味については曖昧である。アロケーターをtype erasureで格納してあとからコピーのために元の型を取り出すのも煩わしい。既存の実装を見ると、libstdc++はそもそもアロケーターを取るコンストラクターを提供しておらず、libc++は、アロケーターを取るコンストラクターこそあるものの、アロケーターは無視され、MSVCの実装はアロケーターを使うものの、代入でtargetが書き換わった場合に再利用されないので、アロケーターの伝播ができない。

std::functionのアロケーターに対しては、様々な規格上の不備や矛盾が指摘されている。

そのため、std::functionからアロケーターサポートを取り除く。これはdeprecated扱いではなく。直ちに取り除く。

P0304R1: C++ Standard Library Issues Resolved Directly In Oulu

Oulu会議で採用された標準ライブラリに対する問題の解決案。

P0305R1: Selection statements with initializer

初期化子つき選択文

以下のようなコードを書くことはないだろうか。

auto obj = get_object() ;

if ( obj.is_valid() )
{
    obj.process() ;
}

一般に、変数を初期化し、初期化された変数の状態によって条件分岐し、分岐先で変数に対して操作を行う処理は多い。しかし、上記のコードには問題がある。まず変数を選択文の外で書かなければならず、選択文のあとにも変数は有効のままだ。変数の利用が選択文だけならば、変数の初期化を選択文に付属させたい。

この提案は、選択文の中で初期化子を使うことができる文法の追加だ。

if ( auto obj = get_object() ; obj.is_valid()
{
    obj.process() ;
}

この改訂版では、switch文に対しても、同様の文法が提案されている。

P0306R0: Comma omission and comma deletion

Cプリプロセッサーマクロ、__VA_ARGS__は、空の引数を受け取ることはできない。

#define F(...) f( __VA_ARGS___ )

// ill-formed
F( ) 

そこで、空の引数も受け付ける__VA_OPT__の提案。

#define F(...) f( __VA_OPT__ )

// f()
F()

[PDF] P0307R2: Making Optional Greater Equal Again

Optionalを再び偉大か同等に!と題された、どこぞの政治スローガンによく似たタイトルの文書。

現在提案されているoptionalは以下のように振る舞う。

optional<X> opt = ....;
assert(( opt >= opt) == true);
assert((*opt >= opt) == true);
assert(( opt >= *opt) == true);
assert((*opt >= *opt) == false);

理由は、optionalのoperator >=は、X型の!operator <を呼んでいるためだ。もしXの型が浮動小数点数だった場合、問題になる。

そういうわけで、正しい挙動は一番下の比較だけだ。いや、正しいというよりは、変えられない挙動というべきかもしれない。すると、一貫性のためには、他の3つの比較も全てfalseになるべきか。それも嫌だ。

この問題を修正するには、optionalのoperator >=が、保持する型のoperator >=を呼べばよい。なので、そのような修正を提案している。

P0308R0: Valueless Variants Considered Harmful

variantの要素型がすべてnoexceptなムーブコンストラクターを持つのであれば、variantはvalueless状態にならないことを保証すべきだという提案。

同様の保証を、std::listにも追加すべきとも提案している。

そして、結局valuelessになるかどうかはnoexceptなムーブコンストラクターがあるかどうかで決まるので、valuelessになるかどうかを判断する、valueless_by_exceptionはいらないのではないかとも提案している。

[PDF] P0309R0: Partial class

partial classの提案。

クラスのprivateなメンバーを変更したとき、そのクラスを使うソースファイルは全て再コンパイルしなければならない。たとえ、privateなメンバーを使わず、またクラスのオブジェクトも生成していないとしてもだ。これを防ぐには、virtual関数を使ったポリモーフィック型を使うか、pimplイディオムを使う必要がある。どちらもメモリ使用量、動的メモリ確保、ポインターのデリファレンスといった追加のコストが必要になる。

そこで、前方宣言を拡張して、partial classを追加する。partial classには、メモリレイアウトを変更しない宣言のみ書ける。

// stack_interface.hpp
partial class stack
{
public :
    void push(int x ) ;
    int pop( ) ;

    bool is_full() ;
    bool is_empty() ;
} ;

partial classは、後続するinternal classで定義できる。

class stack
{
pubic :
    void push( int x ) { buffer[++top] = x ; }
    int pop( ) { return buffer[--top] ; }
    bool is_full() { return top == max_size ; }
    bool is_empty() { top == -1 }

private :
    std::size_t max_size = 100 ;
    int buffer[max_size] ;
    int top = -1 ;
}

partial classは前方宣言と同じように不完全型となる。

partial classは、様々な別名をつけることができる。

partial class stack : export stack_interface1 { ... } ;
partial class stack : export stack_interface2 { ... } ;
partial class stack : export stack_interface3 { ... } ;

実装は別名を全部指定できる。

class stack : partial stack_interface1, partial stack_interface2, partial stack_interface 3 { }

やや筋が悪い提案のように思える。結局、partial classはポインターやリファレンス経由でしか使えないので、完全な定義がある翻訳単位からstaticストレージ、あるいは事前に一括して確保したストレージ上に構築したオブジェクトを、リファレンスかポインター経由でpartial classしか与えられていない翻訳単位に渡して使う形になる。

この提案の価値には疑問だったが、提案者がBMWに所属しているのでようやくわかった。極めて閉鎖的で不自由な組み込みプログラミング向けの機能だ。

組み込みプログラミングなので、メモリの動的確保はない。使うメモリは常に固定で確保している。また、ライブラリはヘッダーファイルとバイナリブロブで提供され、定義がソースコードで提供されることがない。これにより定義を書き換えても、再コンパイルが必要なくなる。ソースコードを見せる必要はない。

極めて筋の悪い提案だ。はっきりいってクソだ。車業界はクソだ。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

22

doorkeeperが有料化するらしい

DoorkeeperというWebサイトがある。これは勉強会、セミナーなどの人が集まるイベントの告知と参加者管理のためのWebサービスを提供している。そのDoorkeeperが有料化するらしい

主催者の皆さまにご利用料をお支払いいただく理由 | Doorkeeper

その理由としては、運営を維持するだけの利益が出ないとのことだ。

Doorkeeprの利益は、イベント参加費の前払いの集金サービスで手数料を徴収することが主なものだったが、そもそもDoorkeeperのイベント主催者の大半は、イベント参加費で利益を上げることを考えておらず、したがって集金サービスもそれほど使われず、利益が出ないとのことだ。

他に利益を上げる方法として、広告や、転職エージェント会社と組むといった方法があるが、広告は広告主がサービスの文脈に沿わないうざい広告しか提案しないのでお断りで、転職会社と手を組むと、利益は転職会社のおこぼれに預かる形になり、転職会社の下で膝を屈することになるのでこれも受け入れがたいという。

確かに、強豪となるWebサービスを提供しているATND(リクルート)とdots(インテリジェンス)は、転職や人材派遣などの事業も行っている。connpass(ビープラウド)は受託開発やpython教育などの事業のようだ。

そこでDoorkeeperは顧客であるイベント主催者から利用料を徴収するそうだが・・・

イベント主催者は利益を目的としていない以上、できるだけコストのかからない方法を選ぶだろうから、あまりうまく行きそうにない。ましてや、無料の競合相手が複数いるような市場では。

Ubuntuでタブレットの画面回転について調べてみた

筆者は長らくタブレットを使っていなかった。これには理由がある。タブレットの多くはiOSやAndroidやWindowsといった不自由なOSが入っていて、極めて使い勝手が悪かったためだ。ところが、今ではx86-64なタブレットも存在する。ARMにGNU/Linuxを入れるのは面倒だが、x86-64なコンピューターであれば、比較的簡単に使えるのではないか。

今回、嫁用のタブレットにUbuntuを入れていろいろと設定したこともあり、自分用にもハックできるタブレットが欲しくなった。そのため、同僚からEndevor TN10Eという極めてCPUの遅いタブレットを格安で買い取っていろいろと遊んでいる。

タッチパネルによるジェスチャーは、Chromiumでは動くが、Firefoxは対応していない。スクリーンキーボードは、筆者がタッチパネルに慣れていないため、とても使いづらい。

Ubuntuと他のOSを比べて気になるのは、画面の自動回転ができないことだ。

画面の回転自体は、xrandrを使えばできる。そこで、以下のようなスクリプトを書いて、画面の回転を切り替えることにした。。

#!/bin/bash

rotation=$(xrandr -q --verbose | grep eDP | egrep -o "(normal|left)" | head -1)

if [ "$rotation" = "normal" ] ; then
    xrandr --output eDP --rotate left
else
    xrandr --output eDP --rotate normal
fi

さて、通常ならば、このスクリプトにわかりやすい名前(rotate-screenなど)をつけてパスの通ったディレクトリに放り込んでおけばいいのだが、タブレットのスクリーンキーボードは打ちづらい。タブレットの利用目的は、移動中にタッチパネルだけでテキストやWebサイトを閲覧することになるだろうから、できれば画面をタッチするだけでこのスクリプトを実行したい。UbuntuのUnityでは、ランチャーに登録するのがいいだろう。

Unityのランチャーにアイコンを登録するには、以下の規格に従った.desktopファイルを作成する必要がある。

Desktop Entry Specification

これを参考に、以下のように書いた。

[Desktop Entry]
Type=Application
Terminal=true
Name=rotate-screen
Exec=/path/to/rotate-screen.sh
StartupNotify=false

このファイルは、例えばrotate-screen.desktopなどと名づけて/usr/local/share/application/か、あるいは~/.local/share/application/の下においておく。あとはこのファイルをGUI上でランチャーにドラッグすれば追加できる。

なぜかTerminal=falseだと、xrandrを呼び出したあとに画面が暗転してマウスカーソルのみ表示される状態になってしまう。

さて、これで画面は回転できるようになったものの、やはり自動で回転させたいところだ。そのためには、コンピューターに搭載されている本体の角度変化を検出するセンサーを読む必要がある、Linuxカーネルでは、Industrial I/O(iio)という名前が付いている。

さて、このiioからセンサー情報を読み取って、D-BUS経由でアクセスできるようにするツールとして、iio-sensor-proxyが存在する。

iio-sensor-proxy/src at master · hadess/iio-sensor-proxy

Ubuntuにはレポジトリに存在するので、apt-get install iio-sensor-proxyしたうえで、systemctl start iio-sensor-proxy.serviceしてmonitor-sensorを実行すれば、加速度、加速角度、光量、コンパスといったセンサーから読み取った結果が表示される。

しかし、調べられたのはここまでで、デスクトップ環境やツールで、ディスプレイの自動回転を行うものがなかなかない。あるにはあるが、どれも適当にでっち上げたプログラムで、あまり洗練された実装ではない。ディスプレイの自動回転を実装するのに必要な道具は全て揃っているので、あとは、あとはiioで加速角度センサーを読み取ってxrandrを叩く簡単なプログラムを書くだけなのだが、果たしてそこまでしてディスプレイの自動回転を実現する理由があるだろうか。そもそも、常にセンサーからの入力を見張って、ディスプレイを回転させるプログラムを実行するということは、それだけ余計に電力を消費するのではないか。

2016-07-23

中古PCを買った

「PCが遅い」と嫁が言う。「10万ぐらいのちゃんとしたPCがほしい」と嫁が言う。

そんな馬鹿な。今時10万円もあれば新品のゲーミングラップトップが買える。観測する限り、嫁はPCでWebブラウザーしか使っていないではないか。閲覧しているWebサイトも、TwitterやFacebookぐらいなものだ。

嫁のPCのスペックを確認するために、Windowsのコントロールパネルを開こうと試みるが、たしかに動作が遅い。型番を調べてググったほうが早そうなほどの時間分またされた挙句、ようやくCPUやメモリ量を確認できた。どうやらAllendale世代のCeleronを積んでいるようだ。

確かに動作が遅いが、不自由でプロプライエタリなソフトウェアであるMicrosoft Windowsについて調べる気にはならない。GNU/Linuxをインストールすればこれよりはマシになるだろう。しかし、聞けばこのPCは卒論を書くのにも使ったという。嫁は全て消しても構わないというが、いろいろとストレージには過去の歴史が残っているであろうから、おそらく消すべきではないのだろう。別のストレージを買ってきて取り替えてからGNU/Linuxをインストールするという手もあるが、スペックも低く、すでに外傷が激しいこの8年ぐらい前のPCをそこまでして温存するべき理由はない。

嫁はコンピューターをよく壊す人間である。スマフォやタブレットは半年も立たないうちに壊してしまうので、最近はガラケーを使っているという。ガラケーのあの形状は、比較的落下時の衝撃に強いのではないかと思う。

以上のことから考えると、数万ぐらいの中古PCを買って、GNU/Linuxをインストールして使わせるのが良いように思う。利用目的には十分な性能と、壊しても惜しくない入手価格であればいいのだ。

そこで、秋葉原にいっていろいろと見て回った結果、AcerのICONIA W700というタブレットを中古で買うことにした。選択した理由は、解像度が1920x1080であるのと、CPUがx86-64で使い勝手がよく、しかもAtomではなくSandy Bridge世代のCore i3-2365Mであることだ。値段は税込みで3万8千円だった。安い理由は、ディスプレイに気泡が入っていることだ。しかし、ディスプレイの隅なので、それほど気にならない場所だ。

タブレットを扱うの初めてだったが、Ubuntuのインストールは何事もなく完了した。

ICONIA W7のBIOSメニューの入り方は本体のWinボタンを押したまま電源ボタンを押し、ベンダーロゴが画面に現れたら両方とも離すという方法であった。ブート順序とSecure bootを無効(私はMicrosoftを信用していないため、Microsoftが署名したバイナリを信用すべき理由がない)にした後、USBストレージに入れたUbuntuをブートしてインストールする。どうやら、Ubuntuのインストーラーはキーボードとマウスを接続していない環境でもインストールが進められるように、スクリーンキーボードが出せるようになっているようだ。今回はキーボードとマウスを使ったので使わなかった。

インストール後に多少の設定をしたのち、使い心地を確かめてみた。UbuntuのUnityは有名なタッチパネルのジェスチャーに対応しているようだ。また、Chromiumはタッチパネルのジェスチャーに対応していたが、Firefoxはまだ対応していなかった。

Ubuntu 16.04には、タブレットの向きに合わせてディスプレイを自動で回転させる機能はなかった。xrandrを使ってディスプレイの回転を切り替える簡単なシェルスクリプトを書いてLauncherにでも設定しておけばとりあえずはいいが、できれば自動で回転して欲しいところだ。GNU/Linuxにはジャイロセンサーの入力を受け取る共通の方法がまだないのだろうか。

さて、今回、初めてタブレットをまともに触ったが、やはり最新のデバイスに触っていないと時代から取り残されると思い、自分用にもタブレットを入手した。Endevor TN10Eだ。これはCPUにAMD A4-1200(Temash)を積んでいて、やや遅い。しかし、ディスプレイの解像度は1920x1080なので、テキストを読むぐらいには使えるだろう。たまたま、同僚がWindowsの再インストールに失敗したものを持っていたので、4500円で買い取った。

Endevor TN10EのBIOSメニューに入るには、音量調整ボタンの+-を同時押ししながら電源ボタンを押す。また、USBキーボードを接続している場合には、F2キーを連打するでも入れる。必要な設定をしたあと、これまたUbuntuをインストールした。

インストール後に使ってみた感想としては、やはりAMD A4-1200は遅い。とはいえ、テキストを読むぐらいには使えそうだ。タブレットの経験に使い潰してみようと思う。

さて、もうひとつ中古PCを買った。dynabook T95だ。

15.6インチの3840×2160ディスプレイ、Haswell世代のCore i7 4710HQ、Radeon R9 M265X、メモリはDDR3が8GB(16GBに増設可能)、ストレージには1TBのハイブリットHDDがついて、8万5千円ほどだった。

やすい理由は、ディスプレイの真ん中よりやや左に縦一直線におそらく1ピクセル幅の常時白点灯ラインがあることだ。とても気になるが、それ以外のスペックは8万5千円で手に入るならば魅力的だ。

さて、Ubuntuをインストールして設定を終え、いろいろと使ってみたが、結論としては、ディスプレイのライン抜けを考慮しても、やはり4Kディスプレイはいいという結論に至った。

結局、我々晴眼者は、コンピューターからの入力方法に眼球を使っている。したがって、効率化のためには眼球にできるだけ多くのピクセルを叩き込むべきである。高PPIは正義だ。高PPIは未来だ。我々は高PPIだ。

また、AMDのGPUはGNU/Linuxで使うのに都合がいい。Ubuntu 16.04では、AMDの不自由でプロプライエタリなバイナリブロブのドライバーは一掃された。もはやUbuntuのレポジトリにはAMDのバイナリブロブなドライバーは存在しない。AMDのGPU用の自由なドライバー実装は十分な品質に達している。

最近、あまりPCのスペックにこだわりがなくなってしまった。いや、実際には逆で、こだわりがありすぎるために、新しくPCを購入する際には、現時点で最高のスペックのPCを入手しなければ気がすまない。30万円だして現時点で最高のスペックのPCを買ったとしても、一年後には陳腐化するし、常に破損、故障の可能性はある。ならば、最初から安い中古PCを使えばいいのではないか。中古なのでスペックには諦めが尽くし、壊れても安ければ気にならない。

2016-07-22

江添ボドゲ会@8月13日

8月13日に江添の自宅でボドゲ会を下記の要領で開催します。

江添ボドゲ会@8月13日 - connpass

気軽にご参加ください。

2016-07-21

C++標準化委員会の文書: P0290R0-P0299R0

P0290R0: apply() for synchronized_value

N4033で提案されているsynchronized_value<T>に対してapply()関数を提供する提案。第一引数に関数オブジェクトを取り、第二引数以降のsyncrhonized_valueを適用する。

synchronized_value<T> s1, s2, s3 ;

int main()
{
    int i = 0 ;
    apply( [&]( auto && s ) { s = ++i ; }, s1, s2, s3 ) ;

P0292R1: P0292R1: constexpr if: A slightly different syntax

この提案はC++17に採用された。以下の内容はまだ公開されていないが採択されたP0292R2の内容を元にしている。

constexpr ifの提案。この提案は条件付きコンパイルではない。実行されない方のブランチのテンプレートの実体化を防ぐif文だ。

constexpr ifの文法は、if文と条件の間にconstexprキーワードを記述する。


if constepxr ( condition )
    statement
else
    statement

conditionは文脈上boolに変換される。もしconditionがfalseならば、1番目のstatementが、trueならば2番目のstatementが、discarded statement(廃棄文)となる。

constexpr ifの実行時の挙動は、if文と同じだ。conditionの値に応じて、どちらかの文が実行される。ただし、コンパイル時の挙動が少し違う。

constexpr ifを持つテンプレートエンティティが実体化されるとき、discarded statement内のテンプレートの実体化は行われない。

template < typename T >
void f( T t )
{
    if constexpr ( std::is_same_v< std::decay_t<T>, std::string > )
    {
        t.compare( "hello" )
    }
    
}

関数fは、実引数にstd::stringが渡された場合、メンバー関数のcompareを呼び出す。もし実引数にstd::stringが渡されなかった場合は、conditionがfalseになるので、constexpr if文のsubstatementはdiscarded statementとなる。テンプレート内のdiscarded statementは、インスタンス化されないので、変数tにメンバーcompareがなかったとしても、コンパイルエラーにはならない。

constexpr ifは、以前提案されていたstatic ifと違い、条件コンパイルではない。テンプレート内で使った時に、discarded statementがインスタンス化されないだけだ。それ以外はif文と同じだ。

例えば、ill-formedなトークン列は、当然ill-formedになる。

// ill-formed
if constexpr ( false )
{
!@#$%^&*()
}

インスタンス化せずともill-formedなテンプレートのコードは当然ill-formedとなる。

template < typename T >
void f()
{
    if constexpr ( false )
    {// ill-formed
        not_found ;
    }
}

このコードでは、非依存名であるnot_foundを使っているが、not_foundは宣言されていないのでill-formedとなる。

constexpr ifを非テンプレートなコードで使うことはできるが、通常のif文と同じ意味しかない。

void f()
{
    // ifと違いはない
    if constexpr ( false )
    {
    }
}

[PDF] P0295R0: Adopt Selected Library Fundamentals V2 Components for C++17

gcdとlcmをLibrary Fundamentals V2から抜き出してC++17に入れる提案。

P0296R2: Forward progress guarantees: Base definitions

Forward Progress Guarantee(ブロックされていないスレッドはいずれは必ず実行が進む保証)を文面に入れる提案。

[PDF] P0298R1: A byte type definition

1バイトを表現するstd::byte型の提案。

std::byte型は、underlaying typeがunsigned charなscoped enum型として追加される。

ビット列を操作する演算子がオーバーロードされている。

char型は符号の有無が未規定で生のバイト列を扱うには不適切な型である。

P0299R1: Forward progress guarantees for Parallelism TS features

タイトル通り、Parallelism TSにおけるforward progress guaranteeの文面の追加。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-17

ダイヤルQ2風の電話番号でInstagramやGoogleやMicrosoftから金をむしりとれる脆弱性

セキュリティ研究者が、とても興味深い脆弱性を報告して報奨金をもらった記事が上がっている。

How I Could Steal Money from Instagram, Google and Microsoft – Arne Swinnen's Security Blog

プレミアムナンバーという電話上のサービスがある。これは一時期日本で行われていたダイヤルQ2と同等の仕組みを持つサービスで、プレミアムナンバーという電話番号にかけた電話の通話料は、通常より高い。通話料の差分は、電話サービスの提供元に支払われる。

ダイヤルQ2は電話越しに何らかのサービスを提供して、電話料金で利用料を徴収できる、手軽な仕組みだった。その利用例は、投資顧問、アダルト、占い、人生相談、義援金、ダイヤルアップISPなどに利用されていた。ダイヤルQ2自体は2014年に終わったが、海外ではまだ同等の仕組みをもつサービスが残っていて、一般に、プレミアム通話料金率電話番号と呼ばれている。

ところで、一部のWebサイトは、ユーザーが指定した電話番号に自動的に電話をかける機能を提供している。その理由は例えば以下のようなものだ。

  • ユーザーが人間であることを確かめるCAPTCHA文字列を合成音声で伝え、その文字列をWebサイトに入力させるため
  • 二段階認証のセキュリティトークンとなる文字列を合成音声で伝え、その文字列をWebサイトに入力させるため
  • アカウントに登録した電話番号が本人のものであることを確かめるため

それ以外にも理由はあるかもしれないが、ユーザーの入力した電話番号に自動的に電話をかけるという機能は、もし電話番号としてプレミアム番号が与えられた場合、課金される脆弱性がある。この研究者はこの脆弱性を研究し、それぞれ報告した。

Instagram:アカウントへの電話番号のひも付け

Instagramはアカウントに電話番号をひも付けて検索で見つけさせることができるが、その電話番号に対してSMSで文字列を飛ばし、入力させる。もし、文字列が3分以内に入力されない場合、カリフォルニアから電話をかける。通話時間は17秒だ。

電話番号のひも付けリクエストはレートリミットされているので30秒に一回しか送れない。しかし、Instagramはどんな電話番号にでも電話をかけてくれる。たとえば、eurocall24.comでは0.06ポンド/分の割合で課金できる。

したがって、計算をすると、30分で1ポンド、一日で48ポンド、1年で17280ポンド、1アカウントとプレミアム電話番号で稼げることになる。とはいえ、攻撃者は100アカウントほど用意して攻撃速度を100倍にできる。すなわち、一日で4800ポンド、一ヶ月で144000ポンド、一年で1728000ポンドだ。

また、複数のアカウントで一つのプレミアム電話番号を使いまわせる。

Facebookに連絡したところ、これは想定の範囲内であり、対策も講じてあり、許容範囲内のリスクであるとの返答を得た。手で100アカウントをつくって自動化した攻撃をするのは簡単であると重ねて連絡をとったところ、最終的に、2000ドルの報奨金と、慈善団体への4000ドルの寄付を得た。

Googleの場合: 二段階認証

Googleは二段階認証のための6桁のセキュリティトークンを、ユーザーが指定した電話番号に伝えてくる。電話番号はプレミアム番号も受け付ける。妥当なセキュリティトークンを入力しないと、数回ほど電話を試みたあとに、ブロックされる。

しかし、eurocall24.comは電話のSIPサーバーへの転送をサポートしており、SIPクライアント経由で電話内容を聞くことができる。

すると、あとは音声認識してトークンを入力してログインするまでの工程を自動化すればいいだけだ。

しかし、Googleはログインが試みられてさえいればよく、ログインが成功したかどうかまでは判定していない。電話がかかってきたあとにログイン試行さえ行われていればブロックはされない。そのため、音声認識の部分は省略でき、電話がかかってきたらそのアカウントにログインを試みるスクリプトを書いて自動化した。

電話は、一時間あたり10回に制限されているようだ。一回あたりの通話時間は約35秒だ。したがって、一日に12ポンド、一ヶ月で360ポンド、一年で4320ポンドせしめることができる。しかし、攻撃者は100アカウントを使うことで攻撃速度を100倍できる。一日で1200ポンド、一ヶ月で36000ポンド、一年で432000ポンドだ。Googleの場合は、プレミアム番号もアカウントごとにユニークなものが必要とされる。

Googleにバグ報告すると、「その脆弱性を使ってplease.break.in@gmail.comに侵入してみせよ」と返事が来た。そのような脆弱性ではないことを伝えると、「先のメールは手違いで送られたものである」と返事が来た。その後、「この問題は些細なものでセキュリティ上の懸念はほぼなく、バグ報酬に値しない」というメールが来た。問題が存在することをさらに解説すると、「先のメールは自動的に送信されたもので、送るべきではなかった。まだ調べている」と返事が来た。ただし、「金はユーザーデータに比べれば大した問題ではない。金は重要であるには違いないが、損失分を取り戻すのは、ユーザーの信頼を取り戻すことに比べれば、遥かに容易である。皮肉なことは私も認めるが、ユーザーにとっては理的だw」とのコメントもあった。

Googleの最終的な回答としては、「我々は対策を講じてあるが、電話の仕組み上、完全に防ぐことは難しい。大量の金を引き出す試みは、対策により阻止される。そのため、我々はこの報告に対して報奨金を支払わない判断をした。先に述べた如く、Googleの金銭的損失はユーザーのセキュリティほど重要ではない。とはいえ、取り上げるには値する報告なので、殿堂入りリストには載せておく」

Microsoftの場合:Office 365の体験版の登録

Office 365の体験版の登録にあたって、電話番号を入力してMicrosoftに電話をかけさせることができる。電話番号にはプレミアム番号も受け付ける。番号は7回の登録失敗でブロックされる。

しかし、このブロックをすり抜ける2つの方法が発見された。

電話番号の前にゼロを追加する。ゼロは最大18個追加することができる。また、ゼロの代わりにプレミアム番号の国番号を追加することもできる。これにより、以下の数式の回数のブロック回避が行える

\[\sum_{n=1}^{18}n=171\]

トータルの回数は171+1で172通りだ。

電話番号の末尾に最大4桁のランダムな番号を追加する。

\[\sum_{i=0}^{4}10^i=11111\]

するとトータルの回数は

\[(172 \times 11111) \times 7 = {13377644} {電話回数/プレミアム番号} \]

一回の通話には約23秒かかる。計算を簡単にするために20秒にしよう。プレミアム番号の稼ぎは1分あたり0.15ユーロだ。

\[(13377644/3) \times 0.15 = 668882 ユーロ/プレミアム番号\]

Microsoftは同一の電話番号に対する並列した電話を認めている。攻撃者はこの手法を自動化すること多額の金を掠め取れる。

Microsoftにバグ報告したところ、電話番号の前と後に桁を追加してブロックを回避できる仕様が修正された。報奨金として最小の額である500ドルが支払われた。

Microsoftの回答によれば、電話サービスはアウトソースしているため、Microsoft自体には被害はないが、報奨金を支払う判断をしたそうだ。

「これは確かに脆弱性で、しかもうまいものだ。そのため我々は報奨金を支払う判断をした。セキュリティの立場から言えば、我々は顧客を守ることに重点を置いている。この脆弱性は報奨金に値するし修正に値するが、顧客のデータに対するリスクはない。我々は常に、セキュリティ研究者に、我々がユーザーを守るための役に立つような研究をしてくれることを依頼しているが、この場合、守られたのは我々と我々の協力会社のようだ。」

この脆弱性は大したものだ。

作業が早いプログラマーと遅いプログラマーの差の比は4:1

An empirical study of working speed differences between software engineers for various kinds of task

プログラマーの作業速度には差がある。作業速度が早いことだけをもって優秀なプログラマーとは限らない。そのソフトウェアの保守性が悪いかもしれないからだ。しかし、やはり作業速度の早いプログラマーは優秀と見られがちだ。特に、転職界隈では、優秀なプログラマーは、その作業速度の速さを形容して、「ニンジャ」とか「10倍プログラマー」などというタイトルで喧伝されている。さて実際には、プログラマーの作業速度は、全体としてどの程度違うのか。

プログラマーの作業速度が早いものと遅いものの比は、従来、28:1であると言われてきた。この数字には根拠となる研究がある。1967年にGrantとSackmanが公開した論文[1]で、実験をした結果、28:1であると結論しているからだ。

[1]: "E. Eugene Grant and Harold Sackman. An exploratory investigation of programmer performance under on-line and off-line conditions. IEEE Trans. on Human Factors in Electronics, 8(1):33–48, March 1967."

問題は、その実験内容というのが、たった12人の経験豊富なプログラマーの被験者に2つの問題を解かせただけなのだ。

たったの12人の結果など、真の結果からかけ離れている可能性も大いにある。しかし、この論文はあまり批判されることがなく、28:1という数字のみが独り歩きしてしまい、今日の10倍プログラマーなどという都市伝説を生み出している。

この論文は、十分なサンプル数を集めてみたところ、28:1という比を否定した。

そもそも、プログラミングには様々な種類の作業がある。この論文では、プログラミングを以下の作業に分類した。

  • 保守(既存のコードの理解と変更と拡張)
  • 理解(例、特定の質問に応えるなど)
  • テスト/デバッグ(テストとデバッグ)
  • レビュー(誤りがないかの確認)
  • プログラミング(設計、実装、テスト、デバッグ)
  • 設計
  • コーディング(実装)

分類の判断に迷う場合は、プログラミングか保守に分類した。また、純粋なコーディング単体のみの作業はまれなので、分類上はプログラミングになっている。

結果としては、作業の種類によって、作業速度のばらつきには差が見られた。テスト/デバッグやプログラミングでは差が大きかったが、保守や理解では差が小さかった。レビュー作業の時間は差がとても小さかった。

結論として、プログラマーの作業速度の差は、4:1を超えることはめったにない。バラつきの大きい作業においても、大抵は2:1から3:1であった。

体感では、こういう短期間の実験では、乱数が相当に左右するのではないだろうかと思う。運悪くtypoをして何時間も悩むことがよくあるために。

2016-07-14

C++標準化委員会の文書: P0280R0-P0289R0

P0280R0: Initialize unspecified aggregate members with direct list initialization

以下のコードのコンパイルが通るようになる変更。


struct S
{
    explicit S(int a = 0) : _a{a} { }
    int _a;
};

int main()
{
    S s ; // OK
    S arr[2] = { S{} }; // エラー
}

現行の文面ではコンパイルが通らないが、これはコンパイルが通ることが望ましい。

P0281R0: Remove comma elision in variadic function declarations

昔ながらの可変引数関数でコンマを書かずにellipsisを書ける昔ながらの文法を除去する提案。

以下は合法なC++のコードである。


int f( ... ) ; // 1
int f( int i, ... ) ; // 2
int f( int i ... ) ; // 3

1はポータブルな方法で可変引数を取り出すことができない。どんな引数でも受け付けるので、メタプログラミングではよく使われている。

2は通常使う関数の宣言

3は歴史的経緯により今だに認められている2と同等の意味を持つ関数の宣言。iと...の間にコンマを記述していない。

この文書は、3の文法をC++から除去する提案を行っている。この文法はユーザーの混乱の元であり、Variadic Templatesとの文法の曖昧性が発見されていて、将来の言語拡張の妨げにもなるので、廃止するのが望ましいとしている。

例えば、以下のコードは極めて紛らわしい。

template <class... T> void f(T...); // パラメーターパックを引数に取る関数
template <class T> void f(T...);    // T型と可変引数を取る関数

現行のC規格ではコンマ省略が認められていないので、C言語との互換性の問題はない。

[PDF] P0283R1: Standard and non-standard attributes

実装がサポートしていないattribute namespaceは無視するように注釈を付け加える提案。

現行規格は、実装がサポートしていないattributeに対してどのように振る舞うべきか規定していない。実装がサポートしていないattributeに対してコンパイルエラーを出す場合、ユーザーはattributeをマクロで隠すようになる。これではattributeの存在意義が否定されてしまう。そのため、実装がサポートしていないattribute namespaceは無視すべきである。

[[ezoe::foobar]] int i ; // attributeは無視する

P0284R0: Unqualified enumerators in case labels

switch文のconditionがenum型の場合、そのswtich文に属するcase文では、unqualified lookupでenumeratorが見つけられるようにする提案。

以下のコードが、

enum struct E
{
    foo, bar 
} ;

void f( E e )
{
    switch( e )
    {
    case E::foo :
        break ;
    case E::bar :
        break ;
    }
}

以下のように書けるようになる。

enum struct E
{
    foo, bar 
} ;

void f( E e )
{
    switch( e )
    {
    case foo :
        break ;
    case bar :
        break ;
    }
}

これはぜひともほしい変更だ。switchのconditionがenum型であることがわかっているのだから、非修飾名でもenumeratorが見つけられるべきだ。

P0285R0: Using customization points to unify executors

ユーザー定義のexecutorを渡すcustomization pointを設ける提案。

customization pointとは、std名前空間の下に関数テンプレートがありデフォルトの実装がされている。unqualified nameで呼べばADLによって優先されるように書いておけばそちらが優先される。という仕組み。

P0286R0: A networking library extension to support co_await-based coroutines

ネットワークライブラリをco_awaitに対応させる変更の提案。

[PDF] P0287R0: Simple Contracts for C++

contractサポートの提案。preconditionとpostconditionのみに限定している。attributeで関数宣言に記述できる。

だいたい以下のような形になる。

template < typename T >
class array
{
// データメンバーなど
public :
    std::size_t size() ;

    value_type & operator []( std::size_t i )
    [[ expects: i < size() ]] ;

    void resize( std::size_t n )
    [[ ensures: size() == n ]] ;

} ;

機能的には、assert( condition )を関数の前後に挟むのと大して変わらない。プリプロセッサーマクロではなくコア言語によるサポートがあることと、コア言語でサポートされるので、コンパイラーオプションなので有効無効を切り替えられる実装にできるぐらいか。

文書はもうひとつ、[[ assert : condition]]を提案している。

[PDF] P0288R0:A polymorphic wrapper for all Callable objects

unique_functionの提案。std::functionとほぼ同じだが、コピーコンストラクター、コピー代入演算子がない。そのため、コピーできないcallable型を格納できる。

[PDF] P0289R0: Forward declarations of nested classes

ネストされたクラスの前方宣言を認める制限緩和をする提案。以下のように書けるようになる。

class X::A ;
X::A ptr = nullptr ;

現状では、以下のように書かなければならない。

class X
{
    class A ;
} ;

ネストされたクラスの宣言を囲む直前のクラスの定義の中で宣言しなければならない。不完全型のX::Aしか必要ない場面でも、完全型のXが必要になる。つまり、Xの定義が必要になる。

この制限緩和をする提案。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-13

C++14でCommodore 64の開発をする

x86から6502への変換ソフトウェアをつくった上で、GCCでC++14のコードをx86にコンパイルして、そこから6502に変換して、Commodore 64エミュレーターで実行している。

Hacker Newsのツッコミによると、6502ではスタックを表現するのが難しいので、コードもスタックを使うような変数を意図的に避けているのだそうだ。

C++14 for the Commodore 64 [video] | Hacker News

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-12

C++標準化委員会の文書: P0270R0-P0279R0

P0270R0: P0270R0: Removing C dependencies from signal handler wording

シグナルハンドラーの文面を書き直す提案。

現在のC++規格におけるシグナルハンドラーは、C規格との共通項のみ使えると定義している。

しかし、現在のC++規格が参照しているC規格はC11である。ということは、thread_localが共通項になるが、thread_localは使えるべきではない。

C言事の共通項というと、Cリンケージを指定するextern "C"も使えないということになるが、それではシグナルハンドラー自体が宣言できない。

nullptrを使えない技術的な理由は何もない。

など、様々な問題があるので、この機会に文面を新たに書きなおす提案。

一般に、シグナルハンドラーのなかでは、ロックを発生させない操作のみ許されるべきだとしていて、POF(Plain-Old-Function)や、 signal-safe functionという用語を定義している。

現実的には、シグナルハンドラーの挙動は何も変わらない。既存のコードは動くのもの動かないものも含めてそのままだ。

この文面の変更により、例えばlambda式がシグナルハンドラーの中で使えるようになった。というのも、lambda式の実装にはメモリの動的確保が必要ないから、禁止する理由がないためだ。

P0271R0:

T型を特定の型リストで構築した時に、実際に呼ばれるコンストラクターの実引数の型を知るために、実際に呼ばれるコンストラクターの型を返すtype traits、std::direct_init<T>の提案。

std::variantで例外を投げる変換関数を持った型が渡された場合でも例外安全にvariantを実装するために必要。

P0272R1:Give 'std::string' a non-const '.data()' member function

あまりにもひどいクソ提案なので解説する価値なし。CreateProcessの第二引数は書き換えを行うし第一引数にNULLを渡すべきではないしCreateProcessAを使うべきでもない。

[PDF] P0273R0: Proposed modules changes from implementation and deployment experience

Clangでモジュールを実装して使用した経験から、モジュール規格の改良提案。

モジュール宣言はソースファイルのどこにでも書いていいことになっていたが、その仕様だと、ツールはソースファイル全体をスキャンしてモジュール宣言があるかどうか確認しなければならない。モジュール宣言はソースファイルの最初の宣言に書く制約をつける。

異なるモジュールで名前が衝突した場合、異なるエンティティが与えられるが、名前の衝突に対する対策としては名前空間がすでにある。モジュールでも名前衝突を回避する機能を別に提供すると、名前空間が使われなくなる。名前の衝突を回避する方法としては名前空間のみが提供すべきだ。モジュールの外にでるエンティティは名前が衝突した場合エラー。モジュールの外に出ないエンティティは別々になるようにする。

モジュールの循環参照は禁止されているし、その理由は妥当なものだが、それだと全モジュールに同じ宣言を書かなければならず、結局一つのテキストファイルに書いて#includeする方法から逃れることができない。これではモジュールの意味がない。

これを解決するために、モジュールパーティションという機能を提供する。

[PDF] P0274R0:Clump - A Vector-like Sequence Container with Embedded Storage

組み込みのストレージをオブジェクトに持った連続したメモリー上に確保されるコンテナー、clumpの提案。

clumpはvectorに似ているが、stringのsmall string optimizationに似た実装をしている。Boostのsmall_vectorと発想は同じだ。

例えば、以下のようなレイアウトで実装される。

template < typename T, std::size_t N, typename Allocator = std::allocator >
class clump
{
    char buf[ sizeof(t) * N ] ;
    T * ptr ;
} ;

要素数がN以下の場合はオブジェクト自体に埋め込みのストレージを使い、Nより多い要素数を扱うときには、アロケーターによるストレージの動的確保を行う。

vectorとは互換性がないので、置き換えて使うこともできない。例えば、insertはpair<iterator, bool>を返す。boolは、組み込みのストレージに収まったかどうかを返す。

P0275R0: A Proposal to add Classes and Functions Required for Dynamic Library Load

Boost.DLLに似たshared library(DLLや.so)を扱うためのライブラリの提案。純粋にライブラリだけの提案となっている。

std::shared_libraryは、ファイルパスを指定してshared libraryを読み込み、シンボル名が存在するか調べたり、型とシンボル名をしていしてshared library内の参照を得たりできる。

int main()
{
    std::shared_library mylib(std::filesystem::path{"mylib.so"}) ;

    if ( mylib.has("myfunc") )
    {
        auto && myfunc = mylib.get< void(void) >( "myfunc" ) ;
        myfunc() ;
    }

}

shared libraryの遅延読み込みをしたりすることもできる。また、デフォルトではシステムディレクトリーは探さず、オプションを指定する必要がある設計になっている。この理由としてシステムディレクトリを探すのは遅く、ユーザーはたいてい読み込むファイルの場所をわかっているからとしているが、理解できない。

提案ではDLL(Dynamic Load Library)という用語を使っていて、ライブラリにもdllという名称が出てくるが、インターフェース的にはdlopenのラッパーのように感じる。

例えばロード時のオプションのscoped enumは以下の通り。

    // shared library file load modes
    enum class dll_mode {
        default_mode = 0,
        dont_resolve_dll_references,    // DONT_RESOLVE_DLL_REFERENCES
        load_ignore_code_authz_level,   // LOAD_IGNORE_CODE_AUTHZ_LEVEL
        rtld_lazy,                      // RTLD_LAZY
        rtld_now,                       // RTLD_NOW
        rtld_global,                    // RTLD_GLOBAL
        rtld_local,                     // RTLD_LOCAL
        rtld_deepbind,                  // RTLD_DEEPBIND
        append_decorations,             // See [dll.dll_mode]
        search_system_directories       // See [dll.dll_mode]
    };

DONT_RESOLVE_DLL_REFERENCESとLOAD_IGNORE_CODE_AUTHZ_LEVELについてはWin32 APIのLoadLibraryEx由来、RTLDについては、dlopen由来のオプションだ。

append_decorationsというのは、ロードするファイルパスに、実装のデフォルトのプレフィクスやポストフィクスを付けてロードするオプションだ。例えば、"foobar"という共有ライブラリをロードしようとすると、Windowsならば"foobar.dll"を、GNU/Linuxならば"foobar.so"を読み込もうとする。ロードが失敗した場合、元の文字列でロードを試みる。

search_system_directoriesは、システムディレクトリからもファイルを探すオプションだ。

果たして入るだろうか。

P0276R0: A Proposal to add Attribute [[visible]]

共有ライブラリでシンボル名としてexportしたいエンティティに指定できる[[visible]]の追加

現状では、MSVCはエスクポートするシンボル名に__declspec(dllexport)を書かなければならない。GCCでは__attribute__((visibility("default"))を書かなければならない。また、シンボル名を使う際には、MSVCでは__declspec(dllimport)を書かなければならない。GCCでは書く必要がない。

この結果、以下のような汚らしいプリプロセッサーマクロが書かれることになる。

#if EXPORTING
    #   if MSVC
    #       define API __declspec(dllexport)
    #   else
    #       define API __attribute__((visibility("default")))
    #   endif
    #else
    #   if MSVC
    #       define API __declspec(dllimport)
    #   else
    #       define API
    #   endif
    #endif

この提案は既存の拡張機能を追認するものだ。

[PDF] P0277R1: const Inheritance

const派生の追加提案。const派生すると、基本クラスを改変できなくなる。派生クラスは、基本クラスのコンストラクターは呼べるが、非staticデータメンバーは変更できず、const修飾された非staticメンバー関数しか呼べなくなる。

P0278R0: P0278r0 - volatile solutions

volatileの定義を見直す提案。以下の変更をする。

  1. 未初期化のvolatileオブジェクトからの読み込みは未定義
  2. 実装はvolatileオブジェクトの値を推定してはいけない
  3. const volatileオブジェクトには初期化が必要ない

volatileの利用例として、memory mapped I/Oに使うというものがある。このとき、特定のメモリアドレスに対する読み書きアクセスは、必ず副作用が発生してほしい。

int volatile * p = ... ;

*p = 42 ;
*p = 42 ;
int x = *p ;

例えば、上のコードについて考える。同じアドレスに連続して2回同じ値を書き込んでいる。通常ならば、実装は最適化の際に、書き込みは一回で十分だと考えるかもしれない。書き込んだあとにすぐ読みだしている。実装は最適化の際に、xの値をコンパイル時に決定できる。したがって、実装は最適化の結果、以下のようなコードに変換するかもしれない。

*p = 42 ;
int x = 42 ;

volatileでは、読み書きに伴う副作用を無視しないという意味を持つ。したがって、このような最適化を禁止する。

ということを規定する。

P0279R0: Read-Copy Update (RCU) for C++

RCUライブラリの追加提案。

RCUは、ロックフリーなreader-writerを実現する。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2016-07-05

C++標準化委員会の文書: P0260R0-P0269R0

P0260R0: C++ Concurrent Queues

concurrent queueライブラリの提案。

使い方は、普通にpushやpopがあり、空きがなかったり空だったりするqueueに待ちなしで操作を試みるtry_pushやtry_popがあり、ブロックせずに操作を試みるnonblocking_pushとnonblocking_popがある。

P0261R0: C++ Distributed Counters

プログラムでは、様々な情報をカウンターで扱う。マルチスレッド環境では、このカウンターはatomic操作しなければならない。問題は、リードの頻度が低く、ライトの頻度が高いカウンターでは、atomic操作を用いるのはコストが高くつく。

このライブラリは、頻度の低いリードのコスト増と引き換えに、頻度の高いライトのコストが低いカウンターを提供する。

使い方としては、基本的にはgeneral_counterを使う。

general_counter<int> counter ;

void f()
{
    // インクリメントとデクリメント
    ++counter ;
    --counter ;

    // +=, -=
    counter += 10 ;
    counter -= 10 ;

    int result = counter.load() ;
}

カウンターへのライトは、戻り値がvoidで、カウンターの結果は返さない。カウンターの値を読むためには、メンバー関数loadを読む必要がある。

カウンターへの操作が集中する場所では、general_counterの代わりに、counter_brokerを使うことができる。counter_brokerはgeneral_counterへの参照を保持し、カウンターへのライトを一旦受け取り、counter_brokerに反映する。


general_counter<int> counter ;
thread_local counter_broker<int> broker( counter ) ;

void high_contention_thread()
{
    while ( true )
    {
        ++broker ;
    }
}

void f()
{
    int value = counter.load() ;
}

うまくライトの集中する部分を切り分けてcounter_brokerを効果的に使わなければパフォーマンスが出ない設計のようだ。

P0262R0: A Class for Status and Optional Value

P0260で提案されているConcurrent queueでは、状態と値を返す。値は返せることもあるし、返せないこともある。現在の設計は、値を返すか例外を投げるメンバー関数と、状態を返し、値はリファレンスで受け取った引数に書き込むメンバー関数とがある。

concurrent queueでは、値を返せないというのは通常起こりうることなので、例外のようなエラー処理を使うのは好ましくない。また、リファレンスで受け取ったオブジェクトに書き込むというのは、値はデフォルト構築可能であることを要求する。

理想的なインターフェースは、状態と値を同時に返すものだ。値は存在しないこともあるので、optionalが使える。しかし、状態と値のtupleを使うのは面倒だ。

すでに書いたように、concurrent queueでは、値を返せないというのは通常起こりうることなので、例外のようなエラー処理を使うのは好ましくない。したがって、状態と値を同時に返す、status_value< Status, Value >というライブラリを新たに提案する。

この提案は筋が悪い。素直にtupleを使ったほうがいい。tupleの使い勝手が悪いのならば、tupleを改良すべきだ。

P0263R1: Core "tentatively ready" Issues

コア言語で既知の問題で解決案が規格入りする準備のできたもの。

P0264R0: auto operator= considered dangerous

auto operator =有害論。

=defaultで定義される特別なメンバー関数でもautoによる戻り値の型推定をさせる作法を定着させようと言う動きに対し、auto operator =は有害であるとする文書。

autoはリファレンスにならない。

struct A
{
    // 戻り値の型はA
    auto operator = ( A & ) { /*...*/ return *this ; }
} ;

クラスAの代入演算子は、、lvalueリファレンスではなく、コピーを返す。

autoの代わりに、auto &やdecltype(auto)が使える。しかし、それでも問題は残る。

struct A { decltype(auto) operator = ( A && a ) { reteurn swap(a) ; } // 100行のコード decltype(auto) swap( A && a ) { /*...*/ return *this ; } } ;

このクラスでは、もしswapの戻り値の型を変更すると、その他の多くの特別なメンバーの戻り値の型まで影響を受けてしまう。保守しにくいコードになる。

文書の上げる最後の点の問題点はよくわからない。swapのような他のメンバーからも使われている基本的なメンバーの変更をしたら、結果がクラス全体に及ぶのは当然だと思うのだが。

[PDF] P0265R0: SG5 is NOT proposing Transactional Memory for C++17

SG5はトランザクショナルメモリーをC++17に提案しない決定をした。時期尚早である。

現行のトランザクショナルメモリーはあまりにも柔軟すぎて、現実のアーキテクチャがサポートするネイティブのトランザクショナルメモリーに落とし込めず、ジャイアントロックによる実装になるだろうから、さもありなん。

[PDF] P0266R0: Removing Restrictions on requires-Expressions

コンセプトのrequiresをbool値を期待する文脈ならどこにでも書けるように制限を緩和する提案。

筆者は現状のコンセプトは入るべきではないと考えている。

[PDF] P0267R1: A Proposal to Add 2D Graphics Rendering and Display to C++,

2Dグラフィックライブラリの提案。

205ページもある、とても長大なドキュメントだ。

内容は普通のグラフィックライブラリだ。

[PDF] P0268R0: up-to expression

シマンテックによるup-to expressionの提案。以下のような式が、

[a..b)

half-openレンジ、a, a+1, a+2, ... , b-2, b-1を生成する。

以下のように使う。

// {0,1,2,3,4}
std::vector<int> v = [0..5) ;
// "01234"
for ( int i : [0..5) )
    std::cout << i ;

up-to式は、慣習的な数学記法に従った文法を持ち、レンジコンセプトを満たす型のオブジェクトを返す。これは遅延評価されるため、メモリ使用量はmake_pair(a, b)程度であり、サイズb-aの配列ではない。up-to式はレンジオブジェクトを期待するところで使うことができる。

有名なLinuxディストリビューションのC++で書かれている11,423件のパッケージのソースコードをパースしてトークンをカウントしたACTCD16によれば、識別子iは20,224,291回使われている。識別子iは最も多く使われている識別子である。平均して、一つのソースファイルあたり8個の識別子iが使われている。

よく書かれるコード例としては、以下のようなものだ。

for ( int i = 0 ; i < 10 ; ++i ) { /*...*/ }

searchcode.comで検索したところ、for文の90%はこのような形をとっている。

このようなfor文のうち、半分はrange-based forに置き換えることができる。残りの半分はup-to式に置き換えることができる。

for ( int i : [0..10) ) { /* ... */ }

up-to式はイテレーターやポインターに使うこともできる。

for ( auto iter : [ v.begin()..v.end() ) )
{
    std::cout << *iter ;
}

up-to式はレンジとしてcomposableである。


using namespace ranges::view;
for (int i : [0..5) | reverse)
    print(i); // outputs 4 3 2 1 0
for (int i : [0..10) | stride(3))
    print(i); // outputs 0 3 6 9
for (int i : [0..10) | stride(3) | reverse)
    print(i); // outputs 9 6 3 0

up-to式は式である。その結果は変数に格納できる。

void f()
{
    auto one_to_five = [0..5) ;

    for ( int i : one_to_five ) ;

    auto f = []( auto x ) { return x ; } ;
    auto a = f( one_to_five ) ;
}

文書では、将来的には[)だけではなく、(), [], (]にも対応できるとしている。

趣旨はわかるのだが、ライブラリでいいのではないのかという気もする。

そして、この提案はコンセプトと、コンセプトによるレンジライブラリが存在することを前提にしているので、使えるとしてもまだまだ先の話だ。

[PDF] P0269R0: Allocator-aware regular expressions

これもシマンテックの提案。std::regexをアロケーターに対応させる提案。

設計上の都合、今更他のライブラリのようにテンプレート実引数でアロケーターを取るわけには行かないので、uses_allocatorを使ってアロケーターを指定する。

シマンテックでは、regexを共有メモリ上に構築するためにregexのあロケーター対応が必須だという。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0