Сегодня я столкнулся с довольно странным случаем разрешения перегрузки. Я сократил это до следующего:
struct S
{
S(int, int = 0);
};
class C
{
public:
template <typename... Args>
C(S, Args... args);
C(const C&) = delete;
};
int main()
{
C c({1, 2});
}
Я полностью ожидал, что C c({1, 2})
будет соответствовать первому конструктору C
, с числом аргументов переменной равным нулю, а {1, 2}
рассматривается как конструкция списка инициализатора объекта S
.
Однако я получаю ошибку компилятора, которая указывает, что вместо этого он соответствует конструктору удаленных копий C!
test.cpp: In function 'int main()':
test.cpp:17:15: error: use of deleted function 'C(const C &)'
test.cpp:12:5: error: declared here
Я могу как-то увидеть, как это может работать - {1, 2}
может быть истолковано как допустимый инициализатор для C, с 1
, являющимся инициализатором для S
(который неявно может быть создан из int, потому что второй аргумент его конструктора имеет значение по умолчанию), а 2
является аргументом с переменным числом аргументов ... но я не понимаю, почему это было бы лучше, особенно если учесть, что рассматриваемый конструктор копирования удален.
Может, кто-нибудь объяснит правила разрешения перегрузки, которые здесь используются, и скажите, существует ли обходной путь, не включающий упоминание имени S в вызове конструктора?
EDIT : Поскольку кто-то упоминал, что сниппет компилируется с другим компилятором, я должен уточнить, что я получил вышеупомянутую ошибку с GCC 4.6.1.
РЕДАКТИРОВАТЬ 2 : я еще больше упростил фрагмент, чтобы получить еще более тревожный сбой:
struct S
{
S(int, int = 0);
};
struct C
{
C(S);
};
int main()
{
C c({1});
}
Ошибка:
test.cpp: In function 'int main()':
test.cpp:13:12: error: call of overloaded 'C(<brace-enclosed initializer list>)' is ambiguous
test.cpp:13:12: note: candidates are:
test.cpp:8:5: note: C::C(S)
test.cpp:6:8: note: constexpr C::C(const C&)
test.cpp:6:8: note: constexpr C::C(C&&)
И в этот раз GCC 4.5.1 также выдает ту же ошибку (за исключением constexpr
s и конструктора перемещения, который он не генерирует неявно).
Я нахожу это очень Трудно поверить, что именно это и было задумано дизайнерами языка ...