こんにちは。
表題の通り、技術書典10 で「詳解 Integromat iPaaS 完全入門」の販売を開始しました。
本書は GitHub にてコンテンツ以外を公開しております。
本書へのフィードバックはこちらへお願い致します。
https://github.com/srz-zumix/book-integromat
こんにちは。
表題の通り、技術書典10 で「詳解 Integromat iPaaS 完全入門」の販売を開始しました。
本書は GitHub にてコンテンツ以外を公開しております。
本書へのフィードバックはこちらへお願い致します。
https://github.com/srz-zumix/book-integromat
※この記事は C++ Advent Calendar 2020 22日目の記事です。
過去に本ブログでも紹介した template の明示的実体化時に private メンバーアクセス可能な仕様を利用した private メンバー変数・関数へのアクセスですが、最近それを使っていて clang だけとある条件でアクセスできないことに気づきました。
この挙動が仕様として正しいのか正しくないのかは筆者ではわからないので、実挙動ベースの話になってしまいますことをご了承ください。
過去の記事
ブログズミ: [C++] Private な関数のテスト
ブログズミ: [C++] 本当に private なところ
こちらは iutest の private メンバーのテストのための機能を使ったサンプルです。
Wandbox 用に圧縮したソースコードを使ってますので、実装を確認したい場合はこちらを御覧ください。
https://github.com/srz-zumix/iutest/blob/master/include/iutest_prod.hpp#L62
#define IUTEST_USE_MAIN #include "iutest.hpp" class A { public: int GetX(void) { return m_x; } private: int m_x; }; IUTEST_MAKE_PEEP(int A::*, A, m_x); IUTEST(Peep, Test1) { A a; IUTEST_PEEP_GET(a, A, m_x) = 42; IUTEST_EXPECT_EQ(42, a.GetX()); IUTEST_EXPECT_EQ(42, IUTEST_PEEP_GET(a, A, m_x)); } IUTEST(Peep, Test2) { A a; IUTEST_PEEP(A, m_x) x(&a); x = 54; IUTEST_EXPECT_EQ(54, a.GetX()); x += x; IUTEST_EXPECT_EQ(108, a.GetX()); IUTEST_EXPECT_EQ(108, x); }
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
https://wandbox.org/permlink/2ZPvpUz1zDe1KHHs
ポイントは IUTEST_MAKE_PEEP と IUTEST_PEEP_GET です。
IUTEST_MAKE_PEEP で private メンバーアクセスするための情報をセットアップし、IUTEST_PEEP_GET で実インスタンスの private メンバーへの R/W を実現しています。
class Hoge { int x; public: Hoge() : x(42) {} private: int GetX() { return x; } private: int gX() { return x; } int gX() const { return x; } int gX(int) { return x; } }; IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, GetX); IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, gX); int main() { Hoge hoge; std::cout << IUTEST_PEEP_GET(hoge, Hoge, GetX)() << std::endl; std::cout << IUTEST_PEEP_GET(hoge, Hoge, gX)() << std::endl; }
Clang の場合はエラー
https://wandbox.org/permlink/roGkNKKwsnaLX7og
GCC の場合は OK
https://wandbox.org/permlink/AWd5A19WWDznccfq
エラーとなるのは gX 関数の PEEP で、オーバーロードされた関数があるとダメなようです。
Visual Studio はバージョンによって static メンバー関数がダメだったりするのは認識してましたが、 clang でもうまくいかないケースがあることがわかりました。
この挙動に関してなにか進展があったら、追記したいと思います。
では。
#!/bin/bash # post_build VERSION=$(docker run --rm ${IMAGE_NAME} --version) docker tag ${IMAGE_NAME} ${DOCKER_REPO}:${VERSION} docker push ${DOCKER_REPO}:${VERSION}
※この記事は C++ Advent Calendar 2020 8日目の記事です。
zapcc は clang ベースのキャッシュを利用した高速な C++ コンパイラーです。
zapcc はサーバープロセスのメモリ上にキャッシュを構築して高速化します。
ヘッダーファイルの解析結果や template のインスタンス化などがキャッシュされます。
プリコンパイルヘッダーを使うよりも生成されたコードもキャッシュされるので高速です。
類似のツールで ccache というキャッシュツールがありますが、こちらは翻訳単位ごとにキャッシュする仕組みなのでフルビルドのときはキャッシュ生成するだけでキャッシュの恩恵を受けられませんが、 zapcc の場合は同じヘッダーファイルを include してるファイルで、template インスタンス化などのキャッシュが利用されるためフルビルドでも高速になります。
また、zapcc サーバープロセスがいる間は別のプログラムのコンパイル時でもキャッシュ利用可能なので複数のプログラムをビルドする際も高速になります。
導入は簡単でビルド・インストール後、 CXX=zapcc++ とするだけで使えます。
自作の C++ テスティングフレームワーク iutest のテスト環境として zapcc インストール済みの Docker を用意してるので、よろしければそちらからでも試せます。
https://hub.docker.com/r/srzzumix/zapcc
zapcc はビルドを高速に行うためにキャッシュをサーバーに蓄えます。
キャッシュはサーバープロセスが生きてるうちは有効です。
つまり、1つの実行ファイルをビルドするときだけでなく、その後に別プログラムをビルドする場合にもキャッシュが有効になります。
ライブラリの大量にあるテストプログラムをビルドするときには、このキャッシュがとても有効に働くと思います。
筆者が開発している iutest でも、複数のテストプログラムがあるのでビルド時間が短縮されるのを期待しましたが、結果は「テストの失敗」でした。
ビルドは特に問題なくできているように見えました、しかしながらテストは失敗している。
どうやらテストが失敗するのは、デフォルト設定ではなくテスト用に機能の有効化・無効化をしているテストでした。
iutest はコンフィグマクロを定義することで任意の機能を有効にしたり、無効にしたりするのですが、これが zapcc と相性最悪でした。。
どうやら、以下のようにとあるテストでコンフィグを変えても、キャッシュされたヘッダーファイルを利用してしまうため、#define が伝わっていないことがわかりました。
#define IUTEST_HAS_VARIADIC_TEMPLATES 0 #include "iutest.hpp"
並列ビルドしているとキャッシュされたヘッダーを利用してしまうため、直列にしました。 -j4 とかせず -j1 を指定。
はい。もこの時点で Zapcc の恩恵を捨てています。いやむしろビルド時間的には悪化する場合も考えられます。。。
次に、キャッシュサーバーのプロセスが生きたままになっているので、1プログラム作る度に kill するようにしました。。。
Makefile はこんな感じになりました。
ifeq ($(CXX_NAME),zapcc++) BUILD4ZAPCC=pkill zapcc++; sleep 1 endif $(TARGETS1) : $(OUTDIR)/% : %.cpp $(IUTEST_HEADERS) $(MAKEFILE) $(BUILD4ZAPCC) $(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) -o $@ $< $(LDFLAGS)
なんか無理くりですが、 iutest はビルド速度改善を目的に zapcc を使っているわけじゃなく、zapcc コンパイラで不具合がないか検証するために使っているので、これでもまぁいいのです。。
zapcc はすごいけど万能ではなかった。
※この記事は C++ Advent Calendar 2020 一日目の記事です。
C++20 で Concepts が導入されました。
コンセプト - cpprefjp C++日本語リファレンス
こういうこと?https://t.co/agPHVeBIV9
— いなむのみたまのかみ🍹☄️🐉🌽☃ (@mitama_rs) December 24, 2019
namespace printer_internal { template<typename Elem, typename Traits, typename T> ::std::basic_ostream<Elem, Traits>& operator << (::std::basic_ostream<Elem, Traits>& os, const T&) { return os << "unknown"; } } // 解決順序 // foo::operator << // ::operator << // ::printer_internal::operator << template<typename T> void print(const T& val) { using namespace ::printer_internal; ::std::cout << val << ::std::endl; }