Is it possible to have an "auto" member variable?
If you declare a class in a lambda expression, you can infer the types of member variables using decltype
:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
auto generic_class = [](auto width1, auto height1) {
class local_class {
public:
decltype(width1) width;
decltype(height1) height;
} local;
local.width = width1;
local.height = height1;
return local;
};
int main()
{
auto obj1 = generic_class(3,std::string("Hello!"));
auto obj2 = generic_class(std::vector<int>{1,2},true);
cout << obj1.height << "\n";
cout << obj2.width[0] << "\n";
return 0;
}
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
.
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.