При попытке выполнить clang-3.4 (скомпилировано из git) не удалось скомпилировать один из моих проектов, жалующихся на неоднозначность при разрешении перегруженных операторов. Я выяснил, что есть два шаблонных оператора, один из которых был объявлен как функция-член, а другой - как не-член, который оба кажется одинаково хорошим.Шаблонное разрешение перегрузки оператора, функция-член против функции без члена
После SSCCE демонстрирует ситуацию:
#include <iostream>
struct ostr {
std::ostream& s;
template<class T>
ostr& operator<<(const T& x) { s << x; return *this; }
};
struct xy {
double x, y;
};
template<class Stream>
Stream& operator<<(Stream& s, const xy& x) {
s << "[" << x.x << ", " << x.y << "]";
return s;
}
int main() {
ostr os{std::cout};
xy x{4, 5};
os << "Value is: " << x <<"\n";
}
Проект компилируется штраф прежде, и я еще раз проверил эту SSCCE с несколькими компиляторами (gcc 4.5
, 4.6
, 4.7
, 4.8
и clang 3.3
), и все они скомпилированных без какой-либо предупреждение (с -Wall -Wextra -pedantic
). Все компиляторы были установлены на стандарт C++ 11/C++ 0x. После добавления CTOR к ostr
, он составлен хорошо, даже на MSVC 2012
и 2010
)
решений как operator<<
сек нечленом проявляет неоднозначность во всех составителей (как ожидалось)
После просмотра стандартных проектов (N3242
и N3690
) Мне не удалось найти что-либо, улучшающее соответствие функций-членов/операторов, чем не-члены.
Так что я не смог доказать, что clang-3.4
ошибается, и мне интересно, кто прав. Таким образом, мой вопрос:
- Действительно ли этот код действителен? Должны ли члены-операторы/функции быть лучше, чем не-члены, и это ошибка в clang-3.4?
- Или все другие компиляторы ошибочны/слишком разрешительны?
Я знаю, что изменение второй operator<<
к не-шаблонной функции (с std::ostream
вместо параметра шаблона) будет разрешить неоднозначность и работать, как ожидалось, но это не точка здесь.
+1 потому что это интересный вопрос; но я бы еще раз, если бы смог, для вашей ясности и тщательности! – Chowlett
«Должны ли члены-операторы/функции быть лучше, чем не-члены» Нет, но они получают в качестве дополнительного параметра ссылку на тип своего класса только для разрешения перегрузки. – dyp
Может быть связано с [этой ошибкой clang] (http://llvm.org/bugs/show_bug.cgi?id=17075) – dyp