読者です 読者をやめる 読者になる 読者になる

ぷろみん

プログラミング的な内容を扱ってます

そもそもがそもそもだった

概要

何故またこっちで書こうと思ったのか。

そもそもの動機

将来性を考えると独自ドメインでブログは運用すべき。
なぜなら資産であるブログ記事を検索サイトに模倣と思われず引っ越す方法がないからだ。

ブログを書くモチベーション

結局は多くの人に見てもらいからだろう。
そうなった時に新しいブログではこのサイトの数%のPVしか付かない。
やる気が湧かないから記事の数も増えないのでPVが増えない。
うーん、バニティメトリクス。

敷居の高さ

記事のクオリティを一定水準まで上げようと思うと、どうしても下書きが増えてしまう。
Qiitaの下書きが10記事までしか保存できないシステムはぐだぐだ言ってねーでさっさと投稿しろ!ってことなんだろうけど、どうも苦手で常に下書きが埋まってしまう。
これは良くないなー、せめて書き切らないとブログを書くモチベーションが保てない。
ということで、こんな感じの頭の中整理みたいな記事も投稿するようにしてみようというチャレンジ。

問題

せっかくなので、現状抱えている問題を列挙しておこう。

こっちは改善案がコメントに色々出ているので対応したいところだが、いかんせんアップデートしようがしまいが改善しようがしまいがアクティブやプレイ、インストール数が変わらないので改善する意欲がわかない。

  • Ghostに付けたい機能が付けられない

twitterのカードサムネに対応したかったけど、やり方が分からなかった。頻繁にアップデートが来るのでもう対応しているのかもしれないが、リリースノートをチェックするのも手間。オープンソースなのでコードを読めば自力で実装もできたかもしれないが、私がブログフレームワークに望んでいることではなかった。
無難にWordPressにした方が良いと思い直したのは良いもののデータ移行のことを考えると面倒になって後回しにしてしまっている。
機能的にははてなブログで十分なんだけど独自ドメイン使おうと思うと月600円。サーバが月500円で借りれることを考えると中々使う気にはなれない。

  • Unityは記事書くの面倒

私は分かりやすく記事を書くのをモットーにしている。何故なら未来の自分へのリファレンスとして書いているからだ。
人は昔のことは忘れるものだ。3年前にやったことを平気で忘れる。そんな時に見返せば当時と同じことが可能になったら素晴らしい。

しかし、Unityの記事を分かりやすく書くのは難しくないが面倒だ。分かりやすくするためには必然的にスクリーンショットを多用する必要があるからだ。

今後の方針

もういっそ、自分のサーバにWordPress上書きインストールで良いかもしれない。せっかくPVが集まってないのだから。

ブログを移転します

はてなブログに頼りっきりでしたが、今は便利になって簡単に個人でもブログサービスを始めることができそうなので移転することにしました。

独自ドメインでGhostを使ってやっていこうかと思います。

tcat.space

見た目をもう少しなんとかしないとなーと思いつつ、古いはてなブログよりはデフォルトでも好みです。

C++で無理矢理クロージャを使ってみる

クロージャ

現在クロージャという表現を使う場合状態を持ったラムダを指す場合が多い気がします。 つまり、ワンライナーで書けるクラスといった感じです。これはC++では関数オブジェクト的な手法で似たようなことができますが、javascript程普通なものではありません。

// javascript
const twice = (action) => { action(); action(); };

const counter = () => {
  let count = 0;
  return () => {
    count++;
    console.log(i);
    return i;
  };  
};

const a = counter();
twice(a); // 1, 2

const b = counter();
twice(b); // 1, 2

C++だと外部ストレージを用いなければできないと思っていましたが、内部ローカル変数を参照でバインドし延命させることでできました。

// C++
auto twice = [](auto action) { action(); action(); };
    
auto counter = [] {
    int count = 0;
    auto increment = [](int& count) { count++; std::cout << count; };
    return std::bind(increment, count);
};
    
auto a = counter();
twice(a); // 1, 2
    
auto b = counter();
twice(b); // 1, 2

応用

これを利用するとfor_each中にコンテキストを保存することができます。
今回は前回のループの値を利用してみました。
素直にローカル変数をキャプチャした方が良いような気もしますが、内部で完結しているのも1つのメリットではないでしょうか。

#include <algorithm>
#include <vector>
#include <functional>
#include <iostream>

namespace {

auto context = [](auto function) {
    auto context = std::make_pair(false, 0);
    auto action = [](decltype(context)& context, auto& function, auto& value) {
        function(value, context);
    };
    return std::bind(action, context, function, std::placeholders::_1);
};

}

int main() {
    std::vector<int> vec = { 5, 10, 15, 20, 25 };
    std::for_each(vec.cbegin(), vec.cend(), context([](auto& value, auto& context) {
        if(context.first) {
            std::cout << value - context.second << std::endl;
        }
        context = std::make_pair(true, value);
    }));
}

参考

クロージャとラムダ式をザックリ解説してみる | No Creativity, No Life!

C++の標準描画ライブラリに入るかもしれないCairoのサンプルをwindows向けにビルドしてみた

cairoとC++

本の虫: Herb SutterがCairoのMLにC++標準規格にCairoを入れられないか打診中

環境

依存関係

$ pacman -S mingw-w64-x86_64-zlib
$ pacman -S mingw-w64-x86_64-libpng
$ pacman -S mingw-w64-x86_64-pixman
$ pacman -S mingw-w64-x86_64-cairo

サンプル

パブリックドメイン

gist.github.com

ビルド

$ x86_64-w64-mingw32-g++ -I/mingw64/include main.cpp -L /mingw64/lib -lcairo -lgdi32

上記ソースとはパスが違うのでcairo-win32.hcairo/cairo-win32.hとしました。

f:id:torini:20160105193421j:plain

基本クラスの継承を考えたデストラクタの属性設定

概要

この記事は間違った情報が多分に含まれるため

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c35-a-base-class-destructor-should-be-either-public-and-virtual-or-protected-and-nonvirtual

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#discussion-make-base-class-destructors-public-and-virtual-or-protected-and-nonvirtual

の翻訳記事に書き換える予定です。

以下元の記事。

実行時の型とポインタの型が違う場合、ただnewするだけでは実行時の型情報がロストするので、ちゃんとtype erasureするかvirtualを付けましょう。

型情報がロストして困る例

#include <iostream>

struct Foo{
    ~Foo(){ std::cout << "Foo" << std::endl; }
};

struct Bar: public Foo{
    ~Bar(){ std::cout << "Bar" << std::endl; }
};

int main(){
    Foo *bar = new Bar();
    delete bar;
}

このコードではBarのデストラクタが実行されません。何故ならBarの型情報をどこにも保持していないからです。

virtualで解決する

struct Foo{
    virtual ~Foo(){ std::cout << "Foo" << std::endl; }
};

そこでデストラクタにvirtualを付けてやるとBarの型情報が(正確にはオーバーライドされた関数へのポインタ)が保持されるのでBarのデストラクタが実行されるようになります。

type erasureで解決する

int main(){
    std::shared_ptr<Foo> bar(new Bar);
}

std::shared_ptrtype erasureというテクニックを使い型を内部で保持します。なのでBarのデストラクタにvirtualが付いていなくてもBarのデストラクタが実行されます。

どっちを使うべきか

Fooインターフェイスの場合継承される意図を明確にする為にvirtualを付けるのが良いと思います。反対にFooがただの一般クラスで同じ機能を流用したくて継承する場合はvirtualを付ける事を推奨しません。こういう場合は使いたい機能をインターフェイスに分離すべきです。

インターフェイスが何らかの事情で用意できない場合ですらstd::shared_ptrで解放するのは意図が明白にならないのでオススメしません。継承先解放用のクラスを作成するのが本来なら良いのですが、このような複雑なテンプレートはしっかりとテストできる環境でのみ作成すべきです。なので、妥協案として継承先解放用のクラスをshared_ptrのエイリアスとして定義すると良いと思います。

余談

std::unique_ptrは型情報を内部で保存していません。なので、継承先のデストラクタは実行されません。

シングルトンを使うのはやめよう

概要

この記事はC++の作者Bjarne Stroustrup等によって書かれたコーディングガイドラインAvoid singletonsの箇所の翻訳です。

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ri-singleton

シングルトンを使うのはやめよう

理由

シングルトンは基本的に変装したグローバルオブジェクトに過ぎないため。

class Singleton {
    // シングルトンオブジェクトが確実に1つだけ作られて
    // プロパティの初期化が行われるようにする
};

シングルトンという発想には多くの亜種がある。 それが問題の1つである。

メモ

あなたがグローバルオブジェクトを変更したくない場合、constまたはconstexprを宣言する。

例外

最初の使用での初期化を行うための純粋なシングルトン(設計を考えなくて良いような)の場合は使用できる。

X& myX()
{
    static X my_x {3};
    return my_x;
}

これは初期化順を制御する最も効果的な解決策の1つだ。 マルチスレッド環境において静的オブジェクトはレースコンディションを引き起こさない。(うっかりそのコンストラクタ内から共有オブジェクトにアクセスしない限り)

もし、あなたが他の大勢のようにシングルトンをオブジェクトを1つだけ作成するためのクラスと定義するのなら、myXのような関数はシングルトンではない。そして、この便利なテクニックはシングルトンを無くすルールの例外ではない。

実施

一般化することは非常に難しい。

  • singletonを含む名前を持つクラスを探す。
  • 作成された単一オブジェクトを探す。(オブジェクトを数えたりコンストラクタを調査する)
  • クラスXの持つpublic static関数が内部に静的なクラスXを持ち、それのポインタや参照を返している場合、それを禁止する。

DirectX12をビルド可能なプロジェクトを作る

前回

ようやくWindows10にしたのでDX12プログラミングを始めてみた - ぷろみん

ビルド

New Project -> Win32 Project -> Empty Project

新しく生成されたフォルダに前回ビルドに成功したサンプルの.cppと.hをコピーしてきます。

Solution Explorerのファイルが並んでいるアイコン(Show All File)をクリックし、先ほどコピーしたファイルを出現させます。
そして、全選択してから右クリックInclude In Projectします。

1からソースを書く場合は省略できますが、d3dx12.hSDKに含まれていないので注意が必要です。

How to: Use the Windows 10 SDK in a Windows Desktop Application

を参考にRetarget SDK Versionすると前回設定した項目が入力可能になります。

プロジェクトのプロパティを開き利用したいバージョンを指定しましょう。
そして、プロジェクトのプロパティの右上にあるConfiguration ManagerからActive solution platformの箇所をx64に変更します。

最後にLinker -> Input -> Additional Dependenciesにd3d12.libdxgi.libを加えるとビルドできます。