2013-02-15 64 views

回答

2

這意味着,如果你創建bind<>類型的對象,你可以申請該函數調用操作到該對象。

像這樣:

bind<int, std::less<int>> b; 
b.v = 2; 
std::cout << b(1) << "\n"; 

片斷代碼可能會打印 「真」 的標準輸出。

1

如果你有一個叫foo類,我敢肯定,你明白它的意思來調用類型的對象的成員函數:

foo f; 
f.bar(); 

你也可以理解,你可以重載某些操作。例如,你可以重載operator+foo,這樣你可以做這樣的事情:

foo f, g; 
f + g; 

現在你也可以重載operator()的一類,它允許你調用它,彷彿它是一個函數:

foo f; 
f(); 

是的,f不是函數,但它是類類型的對象,它重載operator()。這樣做的類類型稱爲函子或函數對象。

在你給出的例子中,bind是一個仿函數。當你創建一個這種類型的對象時,你可以把它稱爲一個函數,傳遞給它一個const T&,它會返回給你一個booloperator()的實現實際上調用了存儲在comp中的函數,並將其傳遞給operator(),aT對象以及類型爲T的成員對象v

1

就目前而言,除了「語法錯誤」之外,它沒有任何意義。例如:

template<T, Op> 

這是不允許的。對於每個模板參數,需要指定它是類型(使用class還是typename)或非類型參數(如int)。由於明顯的意圖是,這兩個應該是類型參數,你需要的東西,如:

template <class T, class Op> 

或:

template <typename T, typename Op> 

對於這種情況,有 classtypename在意義上沒有區別。

struct bind{ 
    T v; 

離開v初始化會導致不確定的行爲,所以你可能不希望允許的。你通常會阻止它通過添加一個構造函數,一個T作爲其參數並初始化v該值:

bind(T const &v) : v(v) {} 

當你有這樣的構造函數,編譯器不會自動生成一個默認的構造函數,所以不再可能創建bind對象,v未初始化 - 正是我們想要的。

雖然創建comp對象:

Op comp; 

是相當無害,它也完全沒有必要。你也可以同樣做與Op()創建一個臨時的實例比較,在這種情況下,這樣的:

bool operator()(const T& a){ 
    return comp(a,v); 
} 

...會變成這樣的事情(和Op comp;簡單地刪除):

bool operator()(T const &a) { 
    return Op()(a, v); 
} 

即使有更正,我會認爲這段代碼已經過時。在C++ 98/03,在那裏你需要一個仿函數提供的算法,比如它會一直在一個情況非常有用:

std::remove_copy_if(a.begin(), a.end(), bind<int, 
        std::back_inserter(b), 
        bind<int, std::less<int> >(5)); 

...這會從a拷貝數來b,去除那些小於5

在C++ 11,但是,大多數(如果不是全部)使用該bind的可能應該寫成lambda表達式,雖然代替,所以上面的位將成爲類似:

std::remove_copy_if(a.begin(), a.end(), bind<int, 
        std::back_inserter(b), 
        [](int x) { return x < 5; }); 

這不僅更短,而且(在lea一旦你習慣了它)比使用std::lessbind將功能放在一起簡單得多。它通常不會在運行時效率上產生任何影響 - lambda基本上是生成類模板的「簡寫」方式,所以它生成的結果與使用bind的代碼非常相似。