![](/img/trans.png)
[英]Perfect forwarding of C++ overloaded and templated functors and its arguments
[英]C++ templated functors
我想知道是否有人可以幫助我使用函子。 我不太了解函子是什么以及它們如何工作,我曾嘗試對其進行谷歌搜索,但我仍然不明白。 函子如何工作以及它們如何與模板一起工作
函子基本上是“功能對象”。 這是一個包裝在類或結構中的函數,可以將其傳遞給其他函數。
它們通過創建自己的類或結構來工作,這些類或結構會重載函數調用操作符(稱為operator())。 通常,您可以通過簡單地就地構造它作為使用函子的函數的參數來創建它的實例。
假設您具有以下條件:
std::vector<int> counts;
現在,您想增加該向量中包含的所有計數。 您可以手動遍歷它們以增加它們,也可以使用一個仿函數。 在這種情況下,合適的函子將如下所示:
struct IncrementFunctor
{
int operator() (int i)
{
return i + 1;
}
}
現在,IncrementFunctor是一個函子,它可以接受任何整數並將其遞增。 要將其應用於計數,可以使用std :: transform函數,該函數將函子作為參數。
std::transform(
counts.begin(), // the start of the input range
counts.end(), // the end of the input range
counts.begin(), // the place where transform should place new values.
// in this case, we put it right back into the original list.
IncrementFunctor()); // an instance of your functor
語法IncrementFunctor()創建該函子的實例,然后將其直接傳遞給std :: transform。 當然,您可以將實例創建為局部變量並將其傳遞,但這更加方便。
現在,到模板上。 std :: transform中函子的類型是模板參數。 這是因為std :: transform不知道(或關心!)您的函子是哪種類型。 它關心的只是定義了擬合操作符(),為此它可以執行以下操作
newValue = functor(oldValue);
編譯器對模板非常聰明,並且通常可以自己弄清楚模板參數是什么。 在這種情況下,編譯器會自動意識到您正在傳入IncrementFunctor類型的參數,該參數在std :: transform中定義為模板類型。 列表也是如此,因此編譯器會自動識別出實際的調用看起來像這樣:
std::transform<std::vector<int>::iterator, // type of the input iterator
std::vector<int>::iterator, // type of the output iterator
IncrementFunctor>( // type of your functor
counts.begin(), // the start of the input range
counts.end(), // the end of the input range
counts.begin(), // the place where transform should place new values.
// in this case, we put it right back into the original list.
IncrementFunctor()); // an instance of your functor
它為您節省了大量的鍵入時間。 ;)
函子是可以通過函數調用運算符來調用/調用的函數 ,在語法上通過附加()
,並在括號內可選地包含參數列表。
這就是模板的全部需求。 就模板而言,對其進行調用的事物是允許使用此語法的事物-換句話說,是自由函數或重寫operator()()
的類的實例。 (“免費”功能只是一個不屬於成員的功能,也就是說,它是全局范圍內的功能或先前包含的名稱空間范圍內的功能。)
在模板元編程之外,我們通常不說自由函數是函子,而是將該名稱保留為重寫operator()()
的類的實例:
struct Foo {
public:
void operator()( int i ) { // do something }
void operator()( int i, char x ) { // do something else }
}
在C ++模板中進行編譯,因此只要語法有意義 ,編譯器將很樂意使用函數或函子:
template<typename T> class Bar {
private int j ;
public:
Bar( int i ) : j(i) {}
void doIt(T t) {
t( j ) ;
}
}
Foo f;
extern void resize( int i ) ; // in some header
Bar<Foo> bf( 5 ) ;
// a Bar that is templated on Foo
Bar< void (&)(int) > br( 5 ) ;
// a Bar that is templated on a function taking int and returning void
br.doit( &resize ) ; // call resize with br.j
bf.doit( f ) ; // call Foo::operator()(int) on Foo f with bf.j
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.