It is valid, but ill-advised in some circles, including my circle.
It is valid in the sense that the member variable will be properly set by the parameter as you desire. Following the execution of the initializer list, the member will be hidden. Any reference to value
will access the parameter. This is likely a bad thing.
It is ill-advised for two reasons. First and foremost, maintainability & confusion. It is unusual to see a parameter and member variable have the same name. Because of this, most programmers will have to stop and think about what it means. After all, you did. Remember that code is written first for programmers, second for compilers. Code that is easy to understand is much better than code that is hard to understand. In a code review I would reject this code on these grounds.
Second, the member hiding will likely be a problem in most scenarios.
I'd suggest coming up with a sane naming scheme and sticking with it. "Sane" means a parameter can never have the same name as a member variable. For example in my naming scheme, member variables are always prepended with m
-- parameters never prepended. So in this scheme your code would become:
struct Struct {
Struct(const T& value) : mValue(value) {}
T mValue;
};
Using this scheme, nobody is confused about what's happening here and nobody has to ask StackOverflow "is this legit?"