コード記法
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の使い方も覚えなければならない