почему шаблонный неконстантный конструктор параметров предпочтительнее данного конструктора копирования

Я хочу, чтобы мой класс можно было использовать в std::variant,

Простой код, который должен работать:

int main()
{
std::variant< int, A > v;

A a(1);
v = a;
}

Мой класс содержит шаблонный конструктор:

 template <typename T> A( T& );

В этот момент начинаются проблемы! Конструктор связывается с вызовом из std::variant и не предусмотрено A(const A&) используется больше.

Для копирования&Вставьте причины полный пример здесь:

#include <iostream>
#include <variant>

class A
{
private:
int x;

public:

A( A&&) {}
A( const A& ) {}
A(){}
~A() {}

A& operator=( const A& ) { return *this;}
A& operator=( A&& ) {return *this;}

template <typename T>
A( T& t  )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

A(int _x):x{_x}{}
};

int main()
{
std::variant< int, A > v;

A a(1);
v = a;
}

Фон:

Почему шаблон здесь?
Проблема начинается при использовании конструктора, который принимает тип сериализатора. Сериализатор может иметь несколько типов, в зависимости от файлов или потоков для сериализации.

Замечание: я знаю, что функциональность конструкторов отсутствует!

1

Решение

Проблема не с std::variant, Проблема с шаблоном конструктора,

template <typename T>
A(T& t)

Такие конструкторы проблематичны, потому что когда аргумент не являетсяconst lvalue типа Aэтот конструктор предпочтительнее, чем конструктор копирования const A&— что обычно не является предполагаемым поведением. Чтобы предотвратить это, мы обычно ограничиваем этот конструктор с помощью SFINAE:

template <typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, A>>>
A(T& t)  // or T&& t

и мог бы рассмотреть возможность сделать это explicit также.

Обычно мы не предоставляем конструкторы копирования, принимающиеconst A&поскольку они избыточны рядом с теми, кто принимает const A&,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]