2015-05-15 40 views
24

考虑this question,大约是下面的代码编译没有:运营商是否应该被宣布为非成员非模板的朋友

std::vector<int> a, b; 
std::cout << (std::ref(a) < std::ref(b)); 

它不会编译,因为vector矢量comparison operators为非成员函数模板和隐式转换不允许考虑。但是,如果经营者,而不是写成非成员非模板,friend功能:

template <class T, class Allocator = std::allocator<T>> 
class vector { 
    // ... 

    friend bool operator<(const vector& lhs, const vector& rhs) { 
     // impl details 
    } 
}; 

那么这个版本的operator<会被发现ADL和被选为最佳可行的过载,和原来的例子将编译。鉴于此,是否有理由宁愿我们目前拥有的非成员函数模板,还是应该将其视为标准中的缺陷?

+0

'operator <<'和流在几个地方也有类似的问题:这会带来一些问题。我可以写一个'template operator <<(std :: basic_ostream &,std :: basic_string &)'* without *,这取决于不止一个前向声明(任一个)。 “Koenig运营商”至少需要其中一个(哪个?),是否需要两者? (这是正切的,因为它是关于两个类型的操作符,而不是像上面那样) – Yakk

+3

我不明白为什么你会写'std :: ref(a) Columbo

+0

@Columbo它适用于'int's。此外,我不知道为什么你会做很多东西 - 并不意味着语言不允许。另外,这可以让你的类使用'operator std :: string()'来比较'string's比较的东西。 – Barry

回答

1

鉴于这种情况,有没有理由喜欢非成员函数模板 我们目前有,还是应该这被认为是一个缺陷 标准?

原因是ADL是否可以找出正确的功能。当这样的搜索需要从给定对象的类型中提取替换的模板参数,然后将它们多次替换为函数模板的模板化参数时,ADL不能这样做,因为在一般情况下没有理由偏好一种模板参数绑定到其他的方法。在该模板的命名空间范围之后定义的非成员函数模板(归因于friend)排除了这种不确定性。