Best way to initialize class's inherited member var of type std::array?
Entity has a member var of type std::array. Student inherits from Entity, and will need to initialize the std::array member var it inherited. Below is the code I'm using to do this, but it involves casting a brace-enclosed list to std::array. I'm not sure this is the correct or optimal way to do this. Using a brace-enclosed or double brace-enclosed list without the cast results in compilation errors. I've tried several other ways of initializing the std::array member var with no succ开发者_StackOverflow中文版ess, so I seem to be stuck with my current method. Is there a better way to do this?:
template<typename... Args> struct Entity {
typedef const char* name_t;
typedef const array<const char*, sizeof...(Args)> source_names_t;
const tuple<Args...> data;
name_t name;
//This will be initialized by derived class Student.
source_names_t source_names;
Entity(
name_t tmp_name
, source_names_t tmp_source_names
)
: name(tmp_name)
, source_names(tmp_source_names)
{}
};
//idnum, fname, lname, married
struct Student : Entity<int, string, string, bool> {
Student()
: Student::Entity(
"student"
//Now Student initializes the array, but does it by casting.
, (source_names_t) {{"id", "lname", "fname", "married"}}
)
{}
};
There are two options, but one relies on runtime size verification. Note the latter in my example is equivalent to a cast. What is wrong with casting?
#include <cassert>
#include <algorithm>
#include <array>
#include <initializer_list>
#include <iostream>
struct A {
typedef std::array<char const*, 3> T;
T data_;
A(std::initializer_list<char const*> const& data) {
assert(data.size() <= data_.size()); // or ==
// of course, use different error handling as appropriate
std::copy(data.begin(), data.end(), data_.begin());
std::fill(data_.begin() + data.size(), data_.end(), nullptr);
}
A(T const& data) : data_ (data) {}
};
int main() {
A a ({"a", "b"});
std::cout << (void const*)a.data_[2] << '\n';
A b ((A::T{"a", "b"})); // might just be the compiler I tested, but the
// extra parens were required; could be related
// to "the most vexing parse" problem
std::cout << (void const*)b.data_[2] << '\n';
return 0;
}
However, it looks like this data is identical for each Student object. Why not either use a virtual method or pass a shared object to the base ctor? You can either copy that object, entity_data_ below—which is equivalent to your current code—or require that it outlive and store a pointer/reference.
struct Student : Entity<int, string, string, bool> {
Student() : Entity<int, string, string, bool>("student", entity_data_) {}
// the template arguments are still required in 0x, I believe
private:
static Entity<int, string, string, bool>::source_names_t entity_data_;
}
精彩评论