簡體   English   中英

C++ 將函數對象作為左值和/或右值傳遞

[英]C++ Passing function objects as lvalues and/or rvalues

我有一個類應該根據用戶提供的謂詞過濾其內容。 我得到的接口規定了對謂詞的引用:

class Test {
  vector<int> data;
public:
  template <class PREDTYPE>
  void filter(PREDTYPE& pred) {
    return;
  }
};

我還得到了一段測試代碼,大致如下所示:

class Filter {
public:
  bool operator()(int) const {
    return false;
  }
};

int main() {
  Test test;
  test.filter(Filter());
}

這不能編譯,說cannot bind non-const lvalue reference of type 'Filter&' to an rvalue of type 'Filter' 如果我將測試代碼更改為

int main() {
  Test test;
  Filter filter;
  test.filter(filter);
}

它有效,但這取決於最終用戶,我無法控制他們的行為。 我嘗試重載 filter 方法,創建一個版本,該版本將按值接受謂詞,然后按引用傳遞它,但這也不能編譯, call of overloaded 'filter(Filter&)' is ambiguous的消息call of overloaded 'filter(Filter&)' is ambiguous

因此我的問題是:是否有可能構造一個過濾器來接受謂詞的右值和左值?

簡而言之,是的(C++11)

您只需要依靠參考折疊規則來確保:

template <typename PREDTYPE>
void filter(PREDTYPE&& pred) { // notice the &&
    // ... Whatever
    // Use perfect forwarding *IF* you can
    std::forward<PREDTYPE>(pred)(some_stuff);
    // Do not use pred after it has been forwarded!
}

這將接受右值和左值,而不必依賴const - 引用(因此您的謂詞仍然可以是可變的)。 如果您堅持使用較舊的 C++ 標准,最好的辦法是改用 const 引用(上面突出顯示了警告)或將過濾器嵌入std::function並依賴調用站點的隱式轉換。

這取決於函數對謂詞的作用。 如果它在返回后保留指向它的引用/指針,則您必須提供一些可以存活足夠長的東西。 但是,如果它沒有保留傳入的謂詞對象的任何內存,則可以將謂詞轉換為左值:

test.filter(static_cast<Filter&>(Filter()));

或者將其包裝在一個簡短的實用函數中:

template <class T>
T& stay(T&& a)
{ return a; }

test.filter(stay(Filter()));

您可能希望將成員函數簽名更改為

template <class PREDTYPE> void filter(PREDTYPE&& pred)

在這里,謂詞作為轉發引用傳遞,對於傳入的左值,它會折疊為左值引用,而右值引用則是對傳入的右值的引用。

通常,函數對象應該按值傳遞。 所以不要超載並將您的簽名更改為

template <class PREDTYPE> void filter(PREDTYPE pred)

可以在此處找到為什么這更好的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM