Возможно ли иметь переменную-член "auto"?
например, я хотел иметь переменную типа auto
потому что я не уверен, какого типа он будет.
когда я пытаюсь объявить его в декларации класса/структуры, это дает мне эту ошибку:
не удается вывести тип auto. Требуется инициализатор
есть ли способ обойти это?
struct Timer {
auto start;
};
4 ответов
вы можете, но вы должны объявить его static
и const
:
struct Timer {
static const auto start = 0;
};
С этим ограничением, вы поэтому не можете иметь start
как нестатический член, и не может иметь разные значения для разных объектов.
если вы хотите различные типы start
для разных объектов, лучше иметь свой класс в качестве шаблона
template<typename T>
struct Timer {
T start;
};
если вы хотите вывести типа T
, вы можете сделать заводская функция, которая выполняет вычет типа.
template<typename T>
Timer<typename std::decay<T>::type> MakeTimer(T&& startVal) { // Forwards the parameter
return Timer<typename std::decay<T>::type>{std::forward<T>(startVal)};
}
видео.
это C++ draft standard
должен сказать об использовании auto
для переменных-членов, в разделе 7.1.6.4 auto specifier
абзац 4
:
автоматический спецификатор типа также может использоваться при объявлении переменной в условии оператора выбора (6.4) или оператора итерации (6.5), в спецификаторе типа-seq в новом типе-id или типе-id нового выражения (5.3.4), в объявлении для диапазона и при объявлении статического элемента данных с инициализатор скобки или равенства, который отображается в спецификации члена определения класса (9.4.2).
поскольку он должен быть инициализирован, это также означает, что он должен быть const
. Что-то вроде следующего будет работать:
struct Timer
{
const static int start = 1;
};
Я не думаю, что это получает вас слишком много, хотя, используя шаблон, как предлагает Марк или теперь, когда я думаю об этом еще, может быть, вам просто нужно Variant Type
в этом случае вы должны проверить Boost.Variant
или Boost.Any
.
нет. Каждый конструктор может иметь свой собственный инициализатор для start
, поэтому не может быть никакого последовательного типа.
Если вы do есть полезное выражение, Вы можете использовать это:
struct Timer {
Foo getAFoo();
delctype(Timer().getAFoo().Bar()) start;
Timer() : start(getAFoo().Bar()) { /***/ }
};
Это также может быть достигнуто с помощью руководств вычета, они были введены в C++17 и недавно (наконец) была добавлена поддержка в VC++ (clang и GCC уже имели его).
https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
например:
template <typename>
struct CString;
template <typename T, unsigned N>
struct CString<std::array<T, N>>
{
std::array<T, N> const Label;
CString(std::array<T, N> const & pInput) : Label(pInput) {}
};
template <typename T, std::size_t N>
CString(std::array<T, N> const & pInput) -> CString<std::array<T, N>>;
Это можно использовать для вывода типов членов класса аналогично auto. Хотя переменные-члены должны каким-то образом зависеть от аргументов конструктора.