Есть следующий упрощённый класс:
struct ID {
int id;
std::string string_id;
template<typename String>
explicit ID(String&& string_id) : string_id{std::forward<String>(string_id)}, id{std::stoi(string_id)} {}
ID(const ID& other) : string_id{other.string_id}, id{std::stoi(other.string_id)} {}
};
Вроде как всё нормально, но когда пытаюсь вызвать конструктор копирования, получаю непонятные ошибки из explicit конструктора... В чём проблема?
ID id1("3x5");
ID id2(id1); // ошибка
Тут целая россыпь ошибок:
string_id имеет то же имя, что и поле класса, это чревато адской путанницейstd::forward(string_id) пропущен параметр шаблона StringID id2(id1); будет более предпочтителен конструктор с универсальной ссылкой, а не копирующий (так как он принимает ID &), для исправления достаточно сделать кастование ID id2(::std::as_const(id1)); или доработать конструктор с универсальной ссылкой использую что-нибудь вроде safe_overloadВо-первых, std::forward требует явного указания шаблонного аргумента
string_id{std::forward<String>(string_id)}
Каким образом у вас получилось "все нормально" без вызова конструктора копирования - не ясно.
Во-вторых, ваша универсальная ссылка - "идеальный параметр", который в процессе overload resolution побеждает даже вариант с const ID& из-за необходимости квалификационного преобразования (добавления const) в последнем. Если вы в своем конструкторе копирования уберете const
ID(ID& other)
то "победит" именно он. А так - побеждает ваш
template<typename String> explicit ID(String&& string_id)
который в таком случае получается некорректным.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости