我想知道如何宣告一個回傳型別的物件,std::function當與指向成員函式的指標一起使用時:
int main(){
void foo(std::string, int);
string s = "hi";
auto fn = std::bind(foo, s, std::placeholders::_1);
fn(5);// ok
/*auto fn2 = */std::bind(&std::string::empty, std::placeholders::_1); // error if I uncomment /*auto fn2 = */
std::vector<std::string> vs{"The", "Quick", "Brown", "Fox", "Jumped", "", "Over", "The", "", "Lazy", "Dog"};
auto it = std::find_if(vs.cbegin(), vs.cend(),
std::bind(&std::string::empty, std::placeholders::_1)); // OK
std::cout << "Empty string found at index: " << (it != vs.cend() ? std::distance(vs.cbegin(), it) : -1) << '\n'; // 5
std::cout << "\ndone!\n";
}
- 如果我取消評論,
auto fn2 =我會收到一個錯誤:
||=== Build: Debug in myproj (compiler: GNU GCC Compiler) ===| /home/Itachi57/Desktop/myproj/main.cxx||In function ‘int main()’:| /home/Itachi57/Desktop/myproj/main.cxx|845| in ‘constexpr’ expansion of ‘std::bind(_Func&&, _BoundArgs&& ...) [with _Func = bool (std::__cxx11::basic_string<char>::*)() const noexcept; _BoundArgs = {const std::_Placeholder<1>&}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind_helper<false, bool (std::__cxx11::basic_string<char>::*)() const noexcept, const std::_Placeholder<1>&>::type](std::placeholders::_1)’| /home/Itachi57/Desktop/myproj/main.cxx|845|internal compiler error: Segmentation fault| ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 7 second(s)) ===|
那么為什么如果我呼叫
bind而不存盤它的回傳值 usingauto當將指標系結到成員函式是可以的但我不能存盤該值(新的可呼叫)?事實上,這只是為了練習目的,因為實際上我更喜歡使用
std::mem_fnandstd::function。更新:
如果我從終端運行程式:
g main.cxx -std=c 2a -o prog && ./prog
它作業得很好。
我發現有一天我從 CodeBlocks 中禁用了“復制省略優化”:
-fno-elide-constructors
現在,如果我洗掉它并讓 CodeBlocks 應用它(Copy-elision 選項),程式構建并運行得很好!
- 那么這個錯誤與 Copy-Elision Optimization 有關系嗎?謝謝!
uj5u.com熱心網友回復:
// 取消注釋 /*auto fn2 = */ 時出錯
// OK
實際上,不,這不好。C 標準通常不允許獲取命名空間 std 中定義的函式的地址(無論它們是自由的還是成員的)。例外總是顯式標記為可尋址函式,并且std::string::empty不可尋址。
為什么?實施余地和未來證明。標準可能想要添加多載。實作可能希望使用多載來實作標準規定的行為,甚至模板。為了使之成為可能,并且我們的程式由標準明確定義,我們不能這樣做&std::string::empty。
只需使用 lambda 來包裝不可尋址的標準函式(就像您使用自己的多載集一樣)。實際上......只需使用 lambdas 并忘記std::bind,它們實際上在各個方面都更好。
uj5u.com熱心網友回復:
這是完美的 實作定義:
住在 Coliru
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
void foo(std::string, int) {}
int main()
{
auto fn = std::bind(&std::string::empty, std::placeholders::_1);
std::vector<std::string> vs{"The", "Quick", "Brown", "Fox", "Jumped", "",
"Over", "The", "", "Lazy", "Dog"};
auto it = std::find_if(vs.cbegin(), vs.cend(), fn);
std::cout << "Empty string found at index: "
<< (it != vs.cend() ? std::distance(vs.cbegin(), it) : -1)
<< '\n'; // 5
std::cout << "\ndone!\n";
}
印刷
Empty string found at index: 5
done!
簡化
我會用std::mem_fn:
住在 Coliru
std::vector<std::string> vs{
"The", "Quick", "Brown", "Fox", "Jumped", "",
"Over", "The", "", "Lazy", "Dog",
};
auto it = std::find_if(vs.cbegin(), vs.cend(), std::mem_fn(&std::string::empty));
std::cout << "Empty string found at index: " << (it - vs.begin()) << '\n';
不使用遺留函式型別的系結:
考慮使用 C 11 lambda:Coliru
auto it = std::find_if(vs.cbegin(), vs.cend(),
[](std::string const& s) { return s.empty(); });
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/346458.html
