メモメモ
環境:ubuntu-linux7.04, gcc-3.4, boost-svn-head 1.34.1, 1.04.0 svn-head
問題:gcc環境下でoven::initaial_valuesが曖昧だとか言って通らないことがある
解決:oven/copy_range.hppのpstade_oven_()の中で使われているread(it)のreadを完全修飾名pstade::oven::readに書き換える
oven::readでも曖昧とか言われるのは何故なんだろう?
msvcなら全然問題無かったのに

もうひとつ

次はegg.lazyでstd::powをlazy化してみる

#ifndef LAZY_POW_DWA20071016_HPP

#if _MSC_VER >= 1020
# pragma once
#endif
// _MSC_VER >= 1020

# define LAZY_POW_DWA20071016_HPP

# include <pstade/egg/lazy.hpp>

namespace nlptr
{
  namespace detail_lazy_pow
  {
    struct base
    {
        template< class Myself, class Arg1, class Arg2>
        struct apply
        {
            typedef Arg1 type; // base::apply::typeが戻り値?
        };

        template< class Result, class Arg1, class Arg2>
        Result call(Arg1 a1, Arg2 a2) const // const忘れると駄目
        {
            return std::pow(a1, a2);
        }
    };

    typedef pstade::egg::function<base> op;

  } // namespace detail_lazy_pow

  PSTADE_ADL_BARRIER(nlptr_lazy_pow) {
      namespace egg = pstade::egg;

      PSTADE_POD_CONSTANT(
          (egg::result_of_lazy< detail_lazy_pow::op>::type)
        , pow_lz
      ) = PSTADE_EGG_LAZY_L {{}} PSTADE_EGG_LAZY_R;
  } // adl barrier

  
} // namespace nlptr



# endif
// LAZY_POW_DWA20071016_HPP

上のaccumulateと併わせて使ってみる


#include <pstade/vodka/drink.hpp>

#include <nlptr/algos/numeric.hpp>
#include <nlptr/progress.hpp>
#include <nlptr/math/lazy_pow.hpp>

#include <boost/range.hpp>
#include <pstade/oven/initial_values.hpp>
#include <pstade/oven/transformed.hpp>
#include <pstade/oven/regular.hpp>
#include <pstade/oven/copied.hpp>
#include <pstade/oven/foreach.hpp>

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

#include <iostream>
#include <vector>
#include <boost/format.hpp>
#include <cmath>

#include <boost/typeof/typeof.hpp>


///////////////////////////////////////////////////////////////
// MACRO ALIASES
///////////////////////////////////////////////////////////////

// Boost.TypeOf
#ifdef BOOST_TYPEOF_TYPEOF_HPP_INCLUDED
# define btypeof_ BOOST_TYPEOF
# define bauto_   BOOST_AUTO
// テンポラリを取得するときに便利かも…
# ifdef BOOST_CALL_TRAITS_HPP
#  define auto_ref_(Name,Expr) \
    boost::call_traits<BOOST_TYPEOF(Expr)>::param_type Name = Expr;
# endif
#endif

// Pstade.Oven
#ifdef PSTADE_OVEN_FOREACH
# define foreach_oven PSTADE_OVEN_FOREACH 
#endif

// Boost.Foreach
#ifdef BOOST_FOREACH
# define foreach_ BOOST_FOREACH 
#endif


int main(void) {
    namespace oven = pstade::oven;
    namespace bll = boost::lambda;

    nlptr::progress_timer timer;
    
    std::vector<double> src_data =
        oven::initial_values(
            3.14, 5.00, 3.57, 5.44
          , 2.14, 7.00, 5.00, 3.33
        );

    bauto_(
        src_sum
      , src_data | nlptr::accumulate(0.0)
    );
    
    bauto_( src_num, boost::size(src_data) );

    bauto_(
        src_average
      , src_sum / static_cast<btypeof_(src_sum)>(src_num)
    );

    // 標準偏差の公式の分母
    btypeof_(src_data) denom =
        ( src_data |
          oven::transformed(
              oven::regular(
                  nlptr::pow_lz(bll::_1 - bll::constant(src_average), 2.0)
              ))
          | oven::copied );

    // 標本標準偏差
    bauto_(
        stdev
      , std::sqrt( ( denom | nlptr::accumulate(0.0) )/ src_num )
    );

    // 母集団標準偏差
    bauto_(
        stdevp
      , std::sqrt( ( denom | nlptr::accumulate(0.0) ) / (src_num - 1) )
    );
    
    std::cout <<
        boost::format("標本標準偏差\t: %f\n母集団標準偏差\t: %f\n")
        %stdev %stdevp ;

    return EXIT_SUCCESS;
}

データは(というかネタも)匿名掲示板のスレから頂いてきた
ただ単に色々使ってみただけってコードだけど、まぁいいか

コード記法

id:mb2sync氏の:p-stadeライブラリを使ってstd::accumulateをpipableにしてみる
見様見真似なので正しいかどうかはわからない

#ifndef NUMERIC_DWA20071016_HPP

#if (_MSC_VER >= 1020)
# pragma once
#endif

# define NUMERIC_DWA20071016_HPP

#include <numeric>
#include <boost/range/value_type.hpp>

#include <pstade/adl_barrier.hpp>
#include <pstade/egg/auxiliary.hpp>
#include <pstade/egg/function.hpp>
#include <pstade/pod_constant.hpp>
#include <pstade/egg/pipable.hpp>

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>


// 独自名前空間でpipable objectの定義を行う
namespace nlptr {

namespace accumulate_detail
{
  
  struct baby
  {
      // 戻り値とテンプレートパラメータ(関数オブジェクトの指定は任意なのでdefault値void)
      template< class Myself, class Range, class Value, class Function = void>
      struct apply :
        boost::range_value<Range>
      { };
      
      // 関数本体
      template< class Result, class Range, class Value, class Function >
      Result call(Range& rng, Value const& init, Function const& func) const
      {
          // range_value<Range> == Value
          BOOST_STATIC_ASSERT((
                                  boost::is_convertible<
                                  typename boost::range_value<Range>::type, Value
                                  >::value
          ));
          
          return std::accumulate(boost::begin(rng), boost::end(rng), init, func);
      }
      
      // デフォルトの関数オブジェクト
      template< class Result, class Range, class Value>
      Result call(Range& rng, Value const& init) const
      {
          // range_value<Range> == Value
          BOOST_STATIC_ASSERT((
                                  boost::is_convertible<
                                  typename boost::range_value<Range>::type, Value
                                  >::value
          ));
          
          return std::accumulate(boost::begin(rng), boost::end(rng), init);
      }
  };
  
  typedef pstade::egg::function<baby> op;
  
} // namespace accumulate_detail


// std::accumulateと名前が被る?
PSTADE_ADL_BARRIER(nlptr_accumulate) {
    namespace egg = pstade::egg;
    
    PSTADE_POD_CONSTANT(
        (egg::result_of_pipable< accumulate_detail::op >::type)
      , accumulate
    ) = PSTADE_EGG_PIPABLE_L {{}} PSTADE_EGG_PIPABLE_R;
} // adl barrier


} // namespace nlptr


# endif
// NUMERIC_DWA20071016_HPP

使用例

#include <nlptr/algos/numeric.hpp>

#include <iostream>
#include <pstade/oven/counting.hpp>

#include <boost/lambda/lambda.hpp>

int main(void) {
    namespace oven = pstade::oven;
    using boost::lambda::_1;
    using boost::lambda::_2;
    
    assert(
        ( (oven::counting(0,10)|nlptr::accumulate(0)) == 45 ) &&
        ( (oven::counting(0,10)|nlptr::accumulate(0, _1 + _2)) == 45 )
    );
}

いい加減にboost.testの使い方も覚えなければならない