Возможно ли иметь переменную-член "auto"?

например, я хотел иметь переменную типа auto потому что я не уверен, какого типа он будет.

когда я пытаюсь объявить его в декларации класса/структуры, это дает мне эту ошибку:

не удается вывести тип auto. Требуется инициализатор

есть ли способ обойти это?

struct Timer {

    auto start;

};

4 ответов


вы можете, но вы должны объявить его static и const:

struct Timer {
    static const auto start = 0;
};

рабочий пример в Coliru.

С этим ограничением, вы поэтому не можете иметь 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>>;

https://godbolt.org/z/LyL7UW

Это можно использовать для вывода типов членов класса аналогично auto. Хотя переменные-члены должны каким-то образом зависеть от аргументов конструктора.