Сегодня я столкнулся с довольно странным случаем разрешения перегрузки. Я свел его к следующему:
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
ов и конструктора move, который он не генерирует неявно).
Мне очень трудно поверить, что это то, что задумали разработчики языка...