問題描述
在回答這個問題時(最好閱讀這個重復"),我想出了以下解決運算符依賴名稱解析的解決方案:
While answering this SO question (better read this "duplicate"), I came up with the following solution to dependent name resolution of an operator:
[temp.dep.res]/1:
[temp.dep.res]/1:
在解析依賴名稱時,會考慮來自以下來源的名稱:
In resolving dependent names, names from the following sources are considered:
- 在模板定義點可見的聲明.
- 來自與實例化上下文 (14.6.4.1) 和定義上下文中的函數參數類型相關聯的命名空間聲明.
#include <iostream>
#include <utility>
// this operator should be called from inside `istream_iterator`
std::istream& operator>>(std::istream& s, std::pair<int,int>& p)
{
s >> p.first >> p.second;
return s;
}
// include definition of `istream_iterator` only after declaring the operator
// -> temp.dep.res/1 bullet 1 applies??
#include <iterator>
#include <map>
#include <fstream>
int main()
{
std::ifstream in("file.in");
std::map<int, int> pp;
pp.insert( std::istream_iterator<std::pair<int, int>>{in},
std::istream_iterator<std::pair<int, int>>{} );
}
但是 clang++ 3.2 和 g++ 4.8 沒有找到這個操作符(名稱解析).
But clang++ 3.2 and g++ 4.8 don't find this operator (name resolution).
包含
難道不是定義了模板的定義點"istream_iterator
?
Doesn't the inclusion of <iterator>
define the "point of definition of the template" istream_iterator
?
正如 Andy Prowl 指出的那樣,這與標準庫無關,而是與名稱查找(可以通過模擬具有多個 operator>>
的標準庫來證明,至少一個位于假 istream
的命名空間中).
As Andy Prowl points out, this has nothing to do with the Standard Library, but rather with name lookup (can be proven by mimicking the Standard Library with multiple operator>>
, at least one in the namespace of the fake istream
).
Edit2:一種解決方法,使用 [basic.lookup.argdep]/2 bullet 2
A workaround, using [basic.lookup.argdep]/2 bullet 2
#include <iostream>
#include <utility>
// can include <iterator> already here,
// as the definition of a class template member function
// is only instantiated when the function is called (or explicit instantiation)
// (make sure there are no relevant instantiations before the definition
// of the operator>> below)
#include <iterator>
struct my_int
{
int m;
my_int() : m() {}
my_int(int p) : m(p) {}
operator int() const { return m; }
};
// this operator should be called from inside `istream_iterator`
std::istream& operator>>(std::istream& s, std::pair<my_int,my_int>& p)
{
s >> p.first.m >> p.second.m;
return s;
}
#include <map>
#include <fstream>
int main()
{
std::ifstream in("file.in");
std::map<int, int> pp;
pp.insert( std::istream_iterator<std::pair<my_int, my_int>>{in},
std::istream_iterator<std::pair<my_int, my_int>>{} );
}
當然,您也可以使用自己的pair
類型,只要解決方法在自定義operator>>
的命名空間中引入關聯的類即可.
Of course, you can also use your own pair
type, as long as the workaround introduces an associated class in the namespace of the custom operator>>
.
推薦答案
這里的問題是你調用 operator >>
的點是在 內部的某個地方std
命名空間,參數類型所在的命名空間為 std
.
The problem here is that the point where your call to operator >>
is being made is somewhere inside the std
namespace, and the namespace where the types of the arguments live is std
.
只要編譯器可以在調用發生的命名空間或參數類型所在的命名空間(兩者都是 std
命名空間在這種情況下),無論它是否適用于重載解析(在名稱查找之后執行),它都不會費心尋找 operator > 的更多重載.>
在父命名空間中.
Provided the compiler can find an operator >>
in either the namespace where the call occurs or the namespace where the types of the arguments live (both are the std
namespace in this case), no matter whether it is viable or not for overload resolution (which is performed after name lookup), it won't bother looking for more overloads of operator >>
in parent namespaces.
不幸的是,您的 operator >>
位于全局命名空間中,因此找不到.
Unfortunately, your operator >>
lives in the global namespace and is, therefore, not found.
這篇關于依賴名稱解析命名空間 std/標準庫的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!