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 class/struct declaration it's giving me this error:
Cannot deduce auto type. Initializer required
Is there a way around it?
struct Timer {
auto start;
};
You can, but you have to declare it static and const:
struct Timer {
static const auto start = 0;
};
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)};
}
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>>;
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.
来源:https://stackoverflow.com/questions/18199728/is-it-possible-to-have-an-auto-member-variable