constexpr 楽しいです(挨拶)。先進的な C++er の方々は既に constexpr をばりばり使われていたわけですが「あぁ constexpr、すごいですよねー」みたいな他人事的な感覚でした。が、自分で書いてみると結構楽しいですね。そんなこんなでちょこちょこと書いていたわけですが constexpr const T* func() や constexpr const T& func() ではなく constexpr const T func() という無駄じゃないんですかそれは、というケースでも意味のあるケースが出てきたので書いてみます。
#include <utility> template<typename T> struct wrapper { constexpr wrapper() : t{} {} constexpr wrapper(const T& t) : t{t} {} constexpr wrapper(const wrapper &t) : t{t.t} {} wrapper(wrapper &&t) : t{std::move(t.t)} {} // GCC 4.7 can compile in this case... // constexpr wrapper(wrapper &&t) : t{std::move(t.t)} {} T t; }; template<typename T> constexpr wrapper<wrapper<T>> makeT(T t) { return wrapper<wrapper<T>>(wrapper<T>(t)); } template<typename T> constexpr const wrapper<wrapper<T>> makeCT(T t) { return wrapper<wrapper<T>>(wrapper<T>(t)); } int main(void) { // Can't compile GCC 4.6/4.7 // constexpr auto p1 = makeT<int>(1).t; constexpr auto p2 = makeCT<int>(2).t; return 0; }
なお GCC 4.5 は literal type に対する解釈が違うのでそもそも通りません。const 無い場合は、move constructor が呼ばれて constexpr じゃねぇと怒られます。結局 move を抑止するための const なのですが constexpr 文脈内なら最初っから const 扱いしてくれてもいいんじゃないの?という気はします。規格的にどうなのかも良く分かりませんが。なお、GCC 4.7 だと move constructor に constexpr を付けるとコンパイルできます。もう何が正しいのか良く分かりません。
0 件のコメント:
コメントを投稿