從零開始寫STL—functional
阿新 • • 發佈:2018-03-29
binder 保存 函數調用 mark 獲取 AR ref 返回 log
function C++11 將任意類型的可調用(Callable)對象與函數調用的特征封裝到一起。
這裏的類是對函數策略的封裝,將函數的性質抽象成組件,便於和algorithm庫配合使用
基本運算符 和 基本比較符號組件
template<class Arg, class Result>
struct unary_function
{
typedef Arg argument_type;
typedef Result result_type;
};
template<class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
template<class T>
struct plus : binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x + y;
}
};
template<class T>
struct minus :binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x - y;
}
};
template<class T>
struct multiplies : binary_function<T, T, T>
{
T operator()(const T& x, const T& y) const
{
return x*y;
}
};
template <class T>
struct modulus : binary_function <T, T, T>
{
T operator() (const T& x, const T& y) const
{
return x%y;
}
};
template<class T>
struct negate :unary_function<T, T>
{
T operator()(const T& x) const
{
return -x;
}
};
template<class T>
struct less :binary_function<T, T, bool>
{
bool operator()(const T&lhs, const T& rhs) const
{
return lhs < rhs;
}
};
template <class T>
struct greater : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs) const
{
return lhs > rhs;
}
};
template <class T>
struct equal_to : binary_function <T, T, bool>
{
bool operator() (const T& x, const T& y) const
{
return x == y;
}
};
template<class T>
struct greater_equal : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs)
{
return lhs >= rhs;
}
};
template<class T>
struct less_equal : binary_function<T, T, bool>
{
bool operator()(const T& lhs, const T& rhs)
{
return lhs <= rhs;
}
};
邏輯運算組件
對已經封裝好的函數組件的運行結果增加一層封裝。
template <class Predicate>
class unary_negate
: public unary_function <typename Predicate::argument_type, bool>//參數類型是傳入Predicate的參數類型,返回類型為bool
{
protected:
Predicate fn;
public:
explicit unary_negate(const Predicate& pred) : fn(pred) {}
bool operator() (const typename Predicate::argument_type& x) const
{
return !fn(x);
}
};
template <class Predicate>
class binary_negate
: public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
{
protected:
Predicate fn;
public:
explicit binary_negate(const Predicate& pred) :fn(pred) {}
bool operator() (const typename Predicate::first_argument_type& x,
const typename Predicate::second_argument_type& y) const
{
return !fn(x, y);
}
};
參數綁定
將要調用的參數保存在結構中,調用的時候再傳入
使用typename 和 模板 來指明返回類型 和 參數類型
建議使用explicit來避免隱式類型轉換
template<class Operation>
class binder1st
: public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename Operation::result_type>
{
protected:
typename Operation::first_argument_type val;//要綁定的參數
Operation op;
public:
explicit binder1st(const Operation& operation, const typename Operation::first_argument_type x) :op(operation),val(x) {}
typename Operation::result_type operator()(const typename Operation::second_argument_type& xs)
{
return op(val, x);
}
};
//綁定第二個參數
template<class Operation>
class binder2nd
: public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename Operation::result_type>
{
protected:
typename Operation::second_argument_type val;
Operation op;
public:
explicit binder2nd(const Operation& operation, const typename Operation::second_argument_type x) :op(operation),val(x) {}
typename Operation::result_type operator()(const typename Operation::first_argument_type& xs)
{
return op(x, val);
}
};
不定參數的綁定
底層數據 結構用tuple來實現,對於調用參數的獲取,維護一個tuple inddex 模板類,去在模板中遞歸生成對應下標。
//綁定不定數目 不定類型的參數
//底層數據通過tuple來保存實現
要實現
template <class F, class... Args>
struct binder
{
//使用std::forward 進行完美轉發
//可見 http://en.cppreference.com/w/cpp/utility/forward
binder(F&& f, Args&&... args) :data(std::forward<F>(f), std::forward<Args>(args)...) {}
inline auto operator()()
{
typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, Args...> >::value, 1>::type index_type;
return run2(index_type());
}
template <std::size_t... Indices>
void run2(tuple_indices<Indices...>)
{
//模板展開
invoke(std::move(std::get<0>(data)), std::move(std::get<Indices>(data))...);
}
inline auto invoke(F&& f, Args&&... args)
{
//f 作為函數指針 ,args 作為參數傳入
return std::forward<F>(f)(std::forward<Args>(args)...);
}
//使用tuple來保存數據
std::tuple<F,Args...> data;
};
template <class F, class... Args >
ministl::binder<F,Args...> bind(F&& f, Args&&... args)
{
return binder<F, Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
從零開始寫STL—functional