constexpr な boost::addable

元ネタ:
http://d.hatena.ne.jp/nagoya313/20110718/1311002272


* * *


なにジョジョ
operator+= から operator+ を生成すると constexpr にできない?


ジョジョ それは
operator+= を使うからだよ

     __.. -―─ 、__
    /`       三ミー ヘ、_
  ゝ' ;; ,, , ,,     ミミ  , il ゙Z,
  _〉,..    ////, ,彡ffッィ彡从j彡
  〉,ィiiif , ,, 'ノ川jノ川; :.`フ公)了
 \.:.:.:i=珍/二''=く、 !ノ一ヾ゙;.;.;)
  く:.:.:.:lムjイ  rfモテ〉゙} ijィtケ 1イ'´
   〕:.:.|,Y!:!、   ニ '、 ; |`ニ イj'  逆に考えるんだ
   {:.:.:j {: :} `   、_{__}  /ノ
    〉イ 、゙!   ,ィ__三ー、 j′  「 operator+ から operator+= を生成すればいいさ」
  ,{ \ ミ \  ゝ' ェェ' `' /
-‐' \ \ ヽ\  彡 イ-、    と考えるんだ
     \ \.ヽゝ‐‐‐升 ト、 ヽ、__
      \  ヽ- 、.// j!:.}    ` ー 、
       ヽ\ 厶_r__ハ/!:.{
          ´ / ! ヽ 

* * *


というわけで,書いてみた.

ソース: http://github.com/gintenlabo/pezzi/blob/master/constexpr_addable.cc

#include <utility>

namespace pezzi
{
  template< class T >
  struct addable
  {
    friend T& operator+=( T& lhs, T const& rhs ) {
      lhs = std::move(lhs) + rhs;
      return lhs;
    }
    
    friend T& operator+=( T& lhs, T && rhs ) {
      lhs = std::move(lhs) + std::move(rhs);
      return lhs;
    }
    
  };
  
}

namespace ns
{
  struct hoge
    : private pezzi::addable<hoge>
  {
    int i;
    
    explicit constexpr hoge( int i_ )
      : i( i_ ) {}
    
    friend constexpr hoge operator+( hoge const& lhs, hoge const& rhs )
    {
      return hoge( lhs.i + rhs.i );
    }
    
  };
  
}

#include <iostream>

int main()
{
  using ns::hoge;
  
  constexpr hoge h1(1);
  constexpr hoge h2(2);
  constexpr hoge h3 = h2 + h1;
  
  hoge h4(4);
  h4 += h3;
  
  std::cout << h4.i << std::endl;
  
}

結果:

7


…石を投げないで><