Is it possible to have a member variable of "auto"?

For example, I wanted to have a variable of type auto , because I'm not sure what type it will be.

When I try to declare it in a class / struct declaration, it gives me this error:

Unable to infer automatic type. Initializer required

Is there any way?

 struct Timer { auto start; }; 
+11
c ++ struct auto
source share
4 answers

You can, but you must declare it static and const :

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

Working example at Coliru .

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

If you need different start types for different objects, it is better to have your class as a template

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

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

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

Living example .

+22
source share

Here is what the draft C ++ standard says about using auto for member variables, in section 7.1.6.4 auto specifier 4 paragraph 4 :

An automatic type specifier can also be used when declaring a variable in the condition of a select statement (6.4) or an iteration operator (6.5), in the description of the -seq type in the identifier of the new type or in the identifier of the type new-expression (5.3.4) in the for-range declaration and in declaring a static data member with a brace initializer or equal brackets that appears in the class definition member specification (9.4.2) ,

Since it must be initialized, it 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 it gets you too much. Using a template, as Mark suggests, or now that I think about it, maybe you just need a variant type . In this case, you should check Boost.Variant or Boost.Any .

+3
source share

Not. Each constructor can have its own initializer for start , so there cannot be a consistent type.

If you have a useful expression, you can use it:

 struct Timer { Foo getAFoo(); delctype(Timer().getAFoo().Bar()) start; Timer() : start(getAFoo().Bar()) { /***/ } }; 
+1
source share

Indirectly, provided that you are not referencing a member of the class.

Now this can also be achieved using output guides, they were introduced in C ++ 17 and recently (finally) support was added in VC ++ (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 infer types of class members in the same way as auto. Although the member variables must somehow depend on the arguments of the constructor.

0
source share

All Articles