Is it possible to have an “auto” member variable?

人走茶凉 提交于 2019-12-03 23:23:13

You can, but you have to declare it static and const:

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

A working example in Coliru.

With this limitation, you therefore cannot have start as a non-static member, and cannot have different values in different objects.

If you want different types of start for different objects, better have your class as a template

template<typename T>
struct Timer {
    T start;
};

If you want to deduce the type of T, you can make a factory-like function that does the type deduction.

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)};
}

Live example.

Shafik Yaghmour

This is what the C++ draft standard has to say about using auto for member variables, in section 7.1.6.4 auto specifier paragraph 4:

The auto type-specifier can also be used in declaring a variable in the condition of a selection statement (6.4) or an iteration statement (6.5), in the type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4), in a for-range-declaration, and in declaring a static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).

Since it must be initialized this also means that it must be const. So something like the following will work:

struct Timer
{
  const static int start = 1;
}; 

I don't think that gets you too much though. Using template as Mark suggests or now that I think about it some more maybe you just need a variant type. In that case you should check out Boost.Variant or Boost.Any.

No. Each constructor could have its own initializer for start, so there could be no consistent type to use.

If you do have a usable expression, you can use that:

struct Timer {

   Foo getAFoo();

   delctype(Timer().getAFoo().Bar()) start;

   Timer() : start(getAFoo().Bar()) { /***/ }
};

Indirectly, provided that you don't reference a member of the class.

This can also now be achieved through deduction guides, these were introduced in C++17 and have recently (finally) support in VC++ has been added (clang and GCC already had it).

https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

For example:

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

This can be used to deduce class member types in a similar manner to auto. Although the member variables need to be Dependant somehow on the constructor arguments.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!