書籍『Effective C++』のC++11/14対応である『Effective Modern C++』のドラフト版がリリースされました。価格は$43です。
このバージョンは、完成版ではなく、レビュー中のものになります。正式版のリリースは、10月に予定されています。
正式リリース時には、書籍はフルカラーになる予定だそうです。
追記 2014/07/14 17:37
O'ReillyのEarly Releaseで購入した場合、更新がある度にそれを受け取れて、完成版ももらえるそうです。
C++17の標準ライブラリに入れる予定の機能を、std::expreimental
名前空間で先行してリリースし、使用経験を得るためのTechnical Specificationの状況。
C++14は8月15日まで、各国の投票待ち。
以下のTechnical Specificationを、投票のために提出した。
not1
、not2
を汎用化したnot_fn
(N4076)と、optional
の修正(N4078)を承認した。
そのほか、
#include <iostream> #include <typeinfo> struct Base { virtual void member_function() {} // 仮想関数を持たせておく必要がある }; struct Derived : public Base {}; int main() { Base* p = new Derived(); if (typeid(*p) == typeid(Base)) { std::cout << "Base" << std::endl; } if (typeid(*p) == typeid(Derived)) { std::cout << "Derived" << std::endl; } }
出力:
Derived
破壊的変更なので、ブログに載せておきます。
以下のコミットで、tagged_int
とtagged_real
のコンストラクタを、explicit
に変更しました。
この変更により、これらのクラスを使っていたコードのコンパイルが通らなくなる可能性があります。
この変更をしたのは、以下のようなコードをコンパイルエラーにしたかったからです。
#include <iostream> #include <shand/strong_typedef/tagged_int.hpp> struct Tag {}; using integer = shand::tagged_int<int, Tag>; void f(integer x) {} int main() { f(3); // コンパイルエラーになってほしい // f(integer(3)); // こう渡してほしい }
つまり、関数の引数としてリテラルを渡す際に、それがどの用途の数値型なのかを明示してほしかったのです。
Chronoライブラリのduration
も、コンストラクタがexplicit
になっているので、それに合わせた形になります。
Boost 1.56.0のリリースまでもう少しかかりそうなので、Boostの近況を書きます。
Boostへのライブラリリクエストの方法を改善する。
Boostを進化させるための新たなガイドライン
C++11標準で提供されているduration
のエイリアスは整数のみですが、浮動小数点数もそれなりに使うので、エイリアスを用意しました。
「何秒間で処理を行う」というAPIの引数がdouble
になってる場合がけっこう多いです。
namespace shand { template <class Rep> using nanoseconds_t = std::chrono::duration<Rep, std::nano>; using nanoseconds_f = nanoseconds_t<float>; using nanoseconds_d = nanoseconds_t<double>; using nanoseconds_ld = nanoseconds_t<long double>; template <class Rep> using microseconds_t = std::chrono::duration<Rep, std::micro>; using microseconds_f = microseconds_t<float>; using microseconds_d = microseconds_t<double>; using microseconds_ld = microseconds_t<long double>; template <class Rep> using milliseconds_t = std::chrono::duration<Rep, std::milli>; using milliseconds_f = milliseconds_t<float>; using milliseconds_d = milliseconds_t<double>; using milliseconds_ld = milliseconds_t<long double>; template <class Rep> using seconds_t = std::chrono::duration<Rep>; using seconds_f = seconds_t<float>; using seconds_d = seconds_t<double>; using seconds_ld = seconds_t<long double>; template <class Rep> using minutes_t = std::chrono::duration<Rep, std::ratio<60>>; using minutes_f = minutes_t<float>; using minutes_d = minutes_t<double>; using minutes_ld = minutes_t<long double>; template <class Rep> using hours_t = std::chrono::duration<Rep, std::ratio<3600>>; using hours_f = hours_t<float>; using hours_d = hours_t<double>; using hours_ld = hours_t<long double>; } // namespace shand
角度のstrong typedefは今まで、tagged_real
のサンプルコードとして提供していましたが、たまに使うのでライブラリ化しました。
例:
#include <iostream> #include <shand/angle.hpp> int main() { shand::degree_f deg(45.0f); shand::radian_f rad = shand::angle_cast<shand::radian_f>(deg); std::cout << rad.get() << std::endl; // shand::sin(deg); // compilation error shand::radian_f sin_result = shand::sin(rad); std::cout << sin_result.get() << std::endl; }
出力:
0.785398 0.707107
角度の単位を変換するには、angle_cast()
関数テンプレートを使用します。Chronoライブラリではミリ秒や秒といった単位間の変換を型昇格として表現していますが、ディグリーとラジアンの間には昇格の関係はないと判断し、関数を通して変換することにしました。
ディグリー(度数法)とラジアン(弧度法)の角度型は、以下のように定義しています:
namespace shand { struct degree_tag {}; struct radian_tag {}; template <class FloatingPoint> using degree_t = shand::tagged_real<FloatingPoint, degree_tag>; using degree_f = degree_t<float>; using degree_d = degree_t<double>; using degree_ld = degree_t<long double>; template <class FloatingPoint> using radian_t = shand::tagged_real<FloatingPoint, radian_tag>; using radian_f = radian_t<float>; using radian_d = radian_t<double>; using radian_ld = radian_t<long double>; }
degree_t
とradian_t
が、浮動小数点数型をパラメータにとる、tagged_real
のエイリアステンプレートで、_f
、_d
、_ld
が付いているものが、浮動小数点数型を設定済みのエイリアスになります。
その他、<cmath>
ヘッダで定義されている、いくつかの数学関数で、ラジアンを受け取ったり返したりする必要のあるものは、ラップして強い型付けにしています。
namespace shand { template <class FloatingPoint> radian_t<FloatingPoint> sin(const radian_t<FloatingPoint>& x) { return radian_t<FloatingPoint>(std::sin(x.get())); } ... template <class FloatingPoint> radian_t<FloatingPoint> atan2(const FloatingPoint& y, const FloatingPoint& x) { return radian_t<FloatingPoint>(std::atan2(y, x)); } }