2011年12月25日日曜日

【C++11】 constexpr const

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 件のコメント:

コメントを投稿