[C++] Analyse von std::binary_function, std::bind1st, std::bind2nd, std::bind

In STL gibt es ein Konzept namens „Adapter“, was bedeutet, dass einige Funktionen möglicherweise zwei formale Parameter definieren. Die von einigen Algorithmen benötigten Funktionen erfordern jedoch manchmal einen formalen Parameter und müssen daher angepasst werden. Transformieren Sie eine Funktion, für die ursprünglich nur zwei erforderlich waren Parameter in eine Funktion, die 1 und Parameter benötigt, um normal zu funktionieren. Können Sie genau wie beim Aufladen Ihres Laptops ein stromführendes Kabel und ein Neutralleiter direkt an Ihren Computer anschließen? Um die heimische Normalspannung in die vom Notebook benötigte Nennspannung umzuwandeln, ist unbedingt ein Adapter erforderlich. Daher kommt der „Adapter“.

std::binary_function

Die Definition der Klasse binäre_Funktion ist sehr einfach, der Quellcode lautet wie folgt:

template <class _Arg1, class _Arg2, class _Result>
struct binary_function
{   // base class for binary functions
    typedef _Arg1   first_argument_type;
    typedef _Arg2   second_argument_type;
    typedef _Result result_type;
};

Dies ist eine Vorlagenklasse für eine Binärfunktion, die zwei Eingabeparameter und einen Rückgabewert definiert. Wenn wir möchten, dass unsere Funktoren Adapter unterstützen, müssen wir von der Binärfunktion ableiten.

#include <iostream>
#include <functional>

template<typename T>
class MLess : public std::binary_function<T, T, bool>
{
public:
	bool operator() (const T& a, const T& b) const{
		return a < b;
	}
};

std::binary_function<T, T, bool> Die ersten beiden Parameter stellen den ersten bzw. zweiten Parameter dar, und bool stellt den Rückgabewert des Operators dar. Nach Abschluss dieser Vorbereitungen können Sie std::bind1st und std::bind2nd zur Anpassung verwenden.

std::bind1st、std::bind2nd

  • bind1st ist eine Funktion (im Wesentlichen eine Funktorklasse), die das erste Argument einer Binärfunktion an einen festen Wert bindet
  • bind2nd ist eine Funktion (im Wesentlichen eine Funktorklasse), die das zweite Argument einer Binärfunktion an einen festen Wert bindet

Sie müssen Header-Dateien hinzufügen , wenn sie erneut verwendet werden

Auch die Implementierung von bind1st ist sehr einfach:

template <class _Fn2>
class binder1st : public unary_function<typename _Fn2::second_argument_type, typename _Fn2::result_type>
{   // functor adapter _Func(stored, right)
public:
    typedef unary_function<typename _Fn2::second_argument_type, typename _Fn2::result_type> _Base;
    typedef typename _Base::argument_type                                                   argument_type;
    typedef typename _Base::result_type                                                     result_type;

    binder1st(const _Fn2& _Func, const typename _Fn2::first_argument_type& _Left) : op(_Func), value(_Left)
    {   // construct from functor and left operand
    }

    result_type operator()(const argument_type& _Right) const
    {   // apply functor to operands
        return (op(value, _Right));
    }

    result_type operator()(argument_type& _Right) const
    {   // apply functor to operands
        return (op(value, _Right));
    }

protected:
    _Fn2                               op;      // the functor to apply
    typename _Fn2::first_argument_type value;   // the left operand
};

// TEMPLATE FUNCTION bind1st
template <class _Fn2, class _Ty>
inline binder1st<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
{   // return a binder1st functor adapter
    typename _Fn2::first_argument_type _Val(_Left);
    return (binder1st<_Fn2>(_Func, _Val));
}

Wie aus dem Code ersichtlich ist, ist bind1st eine Funktionsvorlage, die zwei Parameter, _Func und _Left, übergeben muss. binder1st ist eine Funktorklasse. Im Konstruktor wird _Func dem Mitglied op und _Left meinem Mitglied zugewiesen value , die überladene () ruft einfach die Funktion op(value, _Right) auf.

So verwenden Sie bind1st:

auto lessObj = std::bind1st(MLess<int>(), 5);//实际上是返回一个新的函数对象 binder1st ,成员 op 为 MLess<int>() 对象, value 为 5

Hier ist die Bindung von 5 an den ersten Parameter von MLess, nämlich:

bool operator() (const T& b) const{
		return 5 < b;
	}

Im Augenblick:

result_type operator()(const argument_type& _Right) const
{	// apply functor to operands
	return (op(value, _Right));
}

Auf die gleiche Weise: bind2nd ist dasselbe:

#include <iostream>
#include <functional>
#include <algorithm>
#include <list>

template<typename T>
class MTestClass : public std::binary_function<T, T, void>
{
public:
	void operator() (const T& a, const T& b) const{
		if (a > b)
			std::cout << a << std::endl;
	}
};

int main(int argc, char** argv)
{
	std::list<int> nList;
	nList.push_back(10);
	nList.push_back(20);
	nList.push_back(30);
	nList.push_back(40);
	nList.push_back(50);
	nList.push_back(60);

	std::for_each(nList.begin(), nList.end(), std::bind2nd(MTestClass<int>(), 30));
	
	system("pause");
	return 0;
}

std::bind

Wenn Sie std::bind erwähnen, kommt es Ihnen möglicherweise sofort bekannt vor. Ja, dieser Adapter sollte „bekannter“ sein als die beiden vorherigen, und die von ihm bereitgestellten Funktionen decken die ersten beiden Adapter vollständig ab. Beispielsweise wenn Wir verwenden nicht std::bind1st, std::bind2nd, wir können so schreiben:

   int res = count_if(coll.begin(), coll.end(), std::bind(less<int>(), 10, std::placeholders::_1)); // bind1st(less<int>(), 10));
 
   int res = count_if(coll.begin(), coll.end(), std::bind(less<int>(),std::placeholders::_1, 10)); // bind2st(less<int>(), 10));

Guess you like

Origin blog.csdn.net/weixin_43717839/article/details/132635689