Есть ли способ отключить автоматическое объявление для нестандартных типов?

ОБНОВЛЕНИЕ: есть предложение изменить смысл auto в определенных ситуациях.

Неявная оценка «авто» переменных и аргументов Джоэл Фальку и другие.

Неявная оценка должна:

  1. Включите реализации класса, чтобы указать, что объекты этого класса оцениваются в операторе auto;
  2. Позвольте им определить тип оцениваемого объекта;


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.)

10

Решение

Конструктор копирования означает, что вы ожидаете, что класс будет скопирован. 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,

3

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

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

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