лязгом и G отличается в поведении на следующий код:Неоднозначности с участием шаблонного оператора преобразования и неявный конструктор копирования
struct foo
{
foo(int);
};
struct waldo
{
template <typename T>
operator T();
};
int main()
{
waldo w;
foo f{w};
}
Этого код принимается лязгом, с foo(int)
конструктора вызывается. Тем не менее, GCC жалуется неоднозначность между foo(int)
конструктора и неявно сгенерированным копированием и перемещением конструкторами:
test.cpp: In function 'int main()':
test.cpp:15:12: error: call of overloaded 'foo(<brace-enclosed initializer list>)' is ambiguous
foo f{w};
^
test.cpp:15:12: note: candidates are:
test.cpp:3:5: note: foo::foo(int)
foo(int);
^
test.cpp:1:8: note: constexpr foo::foo(const foo&)
struct foo
^
test.cpp:1:8: note: constexpr foo::foo(foo&&)
Кто прав?
Также интересно отметить, что если foo f{w}
изменен на foo f(w)
(обратите внимание на изменение от скобок до скобок), как gcc, так и clang дают ошибку. Это заставляет меня надеяться, что поведение gcc для приведенного выше примера (например, дающее ошибку) является правильным, иначе возникнет странная несогласованность между формами инициализации ()
и {}
.
EDIT: После Kerrek предложение SB «s, я попытался delete
ИНГ конструктор копирования из foo
:
struct foo
{
foo(int);
foo(const foo&) = delete;
};
поведение остается тем же самым.
Я бы с GCC на этом один: Оба преобразования в 'int' и' Foo' возможны, так что это действительно выглядит неоднозначной , Попробуйте удалить или по умолчанию использовать конструкторы copy/move, и сравнить их. –
Удаленные функции @KerrekSB участвуют в разрешении перегрузки. – TemplateRex
@rhalbersma: Хорошая точка! –