Рассмотрим следующий фрагмент:
struct Base { };
struct Derived : Base { };
void f(Base &) { std::cout << "f(Base&)\n"; }
template <class T = int>
void g() {
Derived d;
f(T{} ? d : d); // 1
}
void f(Derived &) { std::cout << "f(Derived&)\n"; }
int main() {
g();
}
В этом случае я считаю, что вызов функции f
в // 1
следует искать на первом этапе, поскольку тип его аргумента однозначно Derived&
, и, таким образом, разрешаться в f(Base&)
, который является единственным в области видимости.
Clang 3.8.0 со мной согласен, но GCC 6.1.0 этого не делает и откладывает поиск f
до второй фазы, где будет найден f(Derived&)
.
Какой компилятор прав?
f
внезапно изменился и включил больше кандидатов, если я изменю условное выражение наT{} ? d : e
в какой-то момент в будущем. Особенно, еслиe
является ссылкой, которая инициализируется с помощьюd
, но может измениться, чтобы ссылаться на что-то другое в будущем. Кроме того, возможность форсировать зависимое разрешение имени для вызова функции с использованием чего-то вродеf((always_void<T>() , arg))
, даже еслиarg
не является зависимым, кажется мне скорее функцией, чем ошибкой. - person bogdan   schedule 01.06.2016noexcept(T{} ? d : d)
, не зависящими от значения, что было бы неправильно (конструкторT
может throw), поэтому необходимо добавить некоторые дополнительные особые случаи. Не уверен, что оно того стоит, но теперь я думаю, что стоит задуматься. Чем больше я думаю об этом, тем интереснее становится твой вопрос! - person bogdan   schedule 01.06.2016noexcept(typeid(T{}))
также не зависит от значения. - person Columbo   schedule 01.06.2016throw
просто не вырезал, не так ли? Хорошая находка, хотя в вашем конкретном примере правильность не затрагивается (T{}
всегда является значением prvalue, поэтому оно не оценивается иtypeid
не может выбрасывать), тогда как для условного это было бы. Однако дляtemplate<class T> void f(T& t) { constexpr bool n = noexcept(typeid(t)); }
у нас есть проблема; Я думаю, что вы только что нашли здесь незаметную стандартную ошибку. И Clang, и GCC рассматривают его как зависящее от значения, хотя GCC неправильно устанавливает его наtrue
во всех случаях. - person bogdan   schedule 01.06.2016