Не получается создать копирующий конструктор для шаблонного класса
template <class FirstType, class SecondType>
struct Pair
{
Pair(const FirstType& first, const SecondType& second)
: first(first), second(second)
{}
Pair(const Pair<FirstType, SecondType>& src) : first(src.first), second(src.second) {}
Pair(const Pair<const FirstType, SecondType>& src) : first(src.first), second(src.second) {}
FirstType first;
SecondType second;
};
int main()
{
Pair<int, int> a(1, 1);
Pair<const int, int> a_copy(a);
}
error: multiple overloads of 'Pair' instantiate to the same signature 'void (const Pair<const const int, int> &)'
UPD:
Нашел конечно одно решение:
template<class Costyl1, class Colsyl2>
Pair(const Pair<Costyl1, Colsyl2>& src) : first(src.first), second(src.second) {}
но мне потом не охото получать сюрприз, когда из Pair<double, double> случайно сделаю копию Pair<int, int>
Ответы (1 шт):
Во-первых, именно копирующий конструктор (Pair(const Pair<FirstType, SecondType>& src)) писать не смысла, компилятор сгенерирует его за вас. И сгенерированный конструктор не будет конфликтовать со вторым (если у них совпадут типы параметров, копирующий просто не создастся).
Во-вторых, второй конструктор у вас написан так, чтобы создавать пару с неконстантными элементами из пары с первым константным, а вы пытаетесь сделать обратное.
Наверное вы хотели вот это:
Pair(const Pair<std::remove_cv_t<FirstType>, std::remove_cv_t<SecondType>>& src)
: first(src.first), second(src.second)
{}
Но мне больше нравится решение с шаблоном. Оно более универсальное - позволит создавать пару с неконстантными элементами из пары с константными, без написания тучи разных конструкторов.
template <typename A, typename B>
Pair(const Pair<A, B>& src) : first(src.first), second(src.second) {}
не охото получать сюрприз, когда из Pair<double, double> случайно сделаю копию Pair<int, int>
Тогда добавьте проверку:
template <typename A, typename B>
Pair(const Pair<A, B>& src) : first(src.first), second(src.second)
{
static_assert(std::is_same_v<std::remove_cv_t<FirstType>, std::remove_cv_t<A>> &&
std::is_same_v<std::remove_cv_t<SecondType>, std::remove_cv_t<B>>,
"Types must differ only in cv-qualifiers.");
}
Или так:
template <typename A, typename B, std::enable_if_t<
std::is_same_v<std::remove_cv_t<FirstType>, std::remove_cv_t<A>> &&
std::is_same_v<std::remove_cv_t<SecondType>, std::remove_cv_t<B>>, std::nullptr_t> = nullptr>
Pair(const Pair<A, B>& src) : first(src.first), second(src.second)
{}
Или так: (C++20 или новее)
template <typename A, typename B> requires
std::same_as<std::remove_cv_t<FirstType>, std::remove_cv_t<A>> &&
std::same_as<std::remove_cv_t<SecondType>, std::remove_cv_t<B>>
Pair(const Pair<A, B>& src) : first(src.first), second(src.second)
{}