ОБНОВЛЕНИЕ: есть предложение изменить смысл auto
в определенных ситуациях.
Неявная оценка «авто» переменных и аргументов Джоэл Фальку и другие.
Неявная оценка должна:
- Включите реализации класса, чтобы указать, что объекты этого класса оцениваются в операторе auto;
- Позвольте им определить тип оцениваемого объекта;
…
C ++ 11-х auto
Ключевое слово отлично.
Однако, по моему мнению, если тип Не обычный (см. например, Что такое "Обычный тип" в контексте семантики перемещения?) использование auto
становится сложно.
Есть ли способ отключить auto
декларация для такого типа?
Предположим, у кого-то есть ref
класс, который имитирует ссылку
double 5.;
ref<double> rd = d; // `ref` behaves like a reference, so it is not a regular type
ref<double> rd2 = rd; // `ref` can be (syntactically) copy constructible, (it is not regular for other reason)
auto r = rd; // now r is not `double`, but EVEN WORST it is `ref<double>`.
(в реальной жизни это был бы более сложный класс, важным моментом является то, что класс под рукой не является регулярным.)
Единственный способ, который я нашел auto r = rd
не работать (дать ошибку компиляции) значит сделать класс не копируемым, однако мне нужен класс, чтобы иметь конструктор копирования (со специальной семантикой, но конструктор копирования все же).
Есть ли способ отключить синтаксис auto r = rd
каким-то образом? когда decltype(rd)
не регулярно.
(Еще лучше было бы как-то сказать компилятору, что auto
надо делать точно).
Примечание: это не очень искусственная проблема, можно увидеть, что этот тип проблемы лежит в основе std::vector<bool>::reference
(который также является справочной оберткой). Отключение (как-то) синтаксиса auto b = v[10]
не решит проблему std::vector<bool>
но это усложнит плохое использование.
Я что-то пропустил? Должен ли я изменить какую-то другую часть дизайна? Если нерегулярные классы имеют черту типа, которая поможет компилятору определить более общее авто (например, выводить bool
за auto b = v[10]
где std::vector<bool> v
.)
Конструктор копирования означает, что вы ожидаете, что класс будет скопирован. auto x = y;
делает копию y
в x
,
Если вам нужна суперспециальная копия, которую вы не хотите запускать автоматически, вы можете использовать прокси-объект.
template <class T>
struct pseudo_copy;
template <class T>
struct pseudo_copy<T const&> {
T const& t;
// T const& can be initialized from T&&:
pseudo_copy(T const& tin) :t(tin) {}
pseudo_copy(T&& tin): t(tin) {}
pseudo_copy(pseudo_copy const&) = delete;
};
template <class T>
struct pseudo_copy<T&&> {
T&& t;
pseudo_copy(T&& tin): t(std::move(tin)) {}
pseudo_copy(pseudo_copy const&) = delete;
};
template <class T>
pseudo_copy<T const&> pseudo(T& t) { return {t}; }
template <class T>
pseudo_copy<T&&> pseudo(T&& t) { return {t}; }
struct strange {
strange(strange const&)=delete;
strange(pseudo_copy<strange const&>) {} // copy ctor
strange(pseudo_copy<strange&&>) {} // move ctor
strange() = default;
};
Теперь мы можем:
strange foo() { return pseudo(strange{}); }
strange x = pseudo(foo());
а теперь каждая попытка скопировать strange
должен пройти вызов pseudo
и использование auto
никогда не является законным, потому что ничто не имеет конструктора копирования.
Вы также можете сделать конструктор копирования закрытым и использовать его для реализации pseudo
Копировать конструктор.
Обратите внимание, что смысл копирования / перемещения ctor ограничен правилами elision в C ++.
В C ++ 17 шаблонный тип удержания типа мог бы сделать:
template <class T>
struct value{
value_type_of<T> v;
value(T in): v(std::forward<T>(in)) {}
};
int x = 3;
value a = std::ref( x );
А также a.v
будет int
,
Других решений пока нет …