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