const char DICTIONARY[][6] = {
"apple",
"sands"
};
class LetterSet {
public:
unsigned int bitfield;
LetterSet(const char letters[5]) {};
};
const LetterSet words[] = {
LetterSet(DICTIONARY[0]),
LetterSet(DICTIONARY[1]),
};
How can I modify the code above to work in the case where DICTIONARY
is too large to feasibly write out by hand? Specifically, I do not understand how to initalize the words
array in any way that is not a runtime loop-through and create each element.
CodePudding user response:
Might not be needed by Carson, but for those looking for a way to transform an array elements to another type at compile time, it's possible using helper templates and std::array
. An example:
template<class T, std::size_t...Is>
auto transform_array_impl(auto&& array, std::index_sequence<Is...>)
{
return std::array<T, sizeof...(Is)>
{{
(T(array[Is]))...
}};
}
template<class T, class U, std::size_t N>
auto transform_array(const U (&array)[N])
{
return transform_array_impl<T>(array, std::make_index_sequence<N>());
}
const auto words = transform_array<LetterSet>(DICTIONARY);
CodePudding user response:
Seems to me the simple solution is to use a std::vector
instead of an array. Then you can do the initialisation in one line.
const std::vector<LetterSet> words(std::begin(DICTIONARY), std::end(DICTIONARY));
CodePudding user response:
Not sure how to do that for an arbitrary variable, but in context of a function template such argument can be built with template recursion:
template<typename T, std::size_t Pos = 0, std::size_t Size, typename F, typename ...Elements>
void makeArray(const F(&arr)[Size], const Elements&... elements) {
if constexpr(Pos < Size) {
makeArray<T, Pos 1>(arr, elements..., arr[Pos]);
} else {
const T newArray[] { T(elements)... };
std::cout << sizeof(newArray) << std::endl;
}
}
You can extend it to a class member, but unfortunately such a recursion doesn't quite work for constructors and you will have to deal with a free function factory (named constructor idiom neither works if you don't want to specify all the template arguments in advance):
template<typename Type, std::size_t Size>
class my_class {
const Type array[Size];
template<typename... Elements>
my_class(const Elements&... elements): array{ elements... } {}
template<typename T, std::size_t Pos, std::size_t S, typename F, typename ...Elements>
friend my_class<T, S> makeMyClass(const F(&arr)[S], const Elements&... elements);
};
template<typename T, std::size_t Pos = 0, std::size_t S, typename F, typename ...Elements>
my_class<T, S> makeMyClass(const F(&arr)[S], const Elements&... elements) {
if constexpr(Pos < S) {
return makeMyClass<T, Pos 1>(arr, elements..., arr[Pos]);
} else {
return my_class<T, S>{ elements... };
}
}
This is how it looks from the client code:
int main(){
const char DICTIONARY[][6] = {
"apple",
"sands"
};
const my_class instance = makeMyClass<LetterSet>(DICTIONARY);
return 0;
}