為什麼用了using namespace std會報錯?
#include &
#include &
#include &using namespace std;
int main()
{
string str{"test!"};
find_if(str.begin(), str.end(), ispunct);
return 0;
}
這個程序在VS下是沒有問題的,而GCC會報錯。
問題的原因是C++里有三種ispunct(不考慮宏實現版本的話),編譯器不知道你要選擇哪一個。一個是來自C的&
int ::ispunct(int c);
一個就是按照C++標準要放在std中的ispunct了,在&
int std::ispunct(int c);
然而還有一個是在&
template &
如果你不加using namespace std,或者使用::ispunct,那麼選中的就會是第一個版本。
如果用std::ispunct或者using namespace std後直接ispunct,由於第二個和第三個都在std里,名字也一樣,編譯器就要想了這該選哪一個呢?因為find_if是個模板函數,這時候編譯器自然要開始抱template argument deduction的大腿,指望從模板聲明中找出可用的篩選信息。
來看看find_if怎麼聲明的:template&
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
。。。這不坑爹嗎?pred參數啥限制條件也沒有怎麼判斷?
自然編譯器只能不知所措,被compile error淹沒了。如果find_if長這樣:template&
InputIterator maki (InputIterator first, InputIterator last, bool(*pred)(Nico))
那編譯器就可以判斷出來這裡第三個參數必須是個單參數的函數指針,就不會有歧義了。
等等,程序里不是沒包含&嘗試編譯以下程序:
#include &
#include &
#include &
using namespace std;
int main() {
bool(*p)(char, const locale) = ispunct; //強行選擇locale版本
}
這段程序在VS上是不通過的,而GCC可以編譯成功。
在GCC中,&根據題主反饋的信息,Gomo Psivarh的回答是正確的,出錯的根源在於名字查找中的不確定。
原答案的解決方案仍是可用的,因為在lambda定義時說明了需要調用ispunct(int),從而消除了不確定。---------以下是原回答-----------ispunct()是&find_if(str.begin(), str.end(), [](int i) {return ispunct(i);} );
我試了一下,編譯通過了,可是你沒有輸出,我也不知結果對不對。
與using namespace std;無關啊,難道你去掉了編譯能通過嗎?ispunct是宏,不是真正的函數
推薦閱讀:
※c++如何在編譯期判斷一個對象是否是字元串字面值?
※C++的std::thread是怎麼進行參數傳遞的?
※怎麼正確書寫C++高階函數?
※你怎麼看 C++11(新的 C++ 標準)裡面的變化?