The c++/cli template below is working, but it seems like there ought to be a way to generalize the template further or add a helper that can create the template instances at compile time.
Was thinking something like http://en.cppreference.com/w/cpp/utility/integer_sequence might work, but need some assistance with the helper / implementer function.
Simplified main to demonstrate the desired syntax vs what is currently used:
int main(array<String^>^ args) {
// the actual number of possible char lengths is sparse (generally)
// but the API allows for 1-1024
List<int>^ varList = gcnew List<int>();
varList->Add(40);
varList->Add(80);
varList->Add(128);
SortedList<int, List<String^>^>^ allStrings = gcnew SortedList<int, List<String^>^>();
// want something like this, but the compiler complains that
// the template is invalid expectes compile-time constant expressions
for each(int key in varList) {
allStrings->Add(key, UpdateTest<key>());
}
// this works, but has 1024 lines of case N:
for each(int key in varList) {
switch (key) {
case 1: allStrings->Add(key, UpdateTest<1>());
case 2: allStrings->Add(key, UpdateTest<2>());
case 3: allStrings->Add(key, UpdateTest<3>());
//... all 1024 possible char[N] sizes...
case 1024: allStrings->Add(key, UpdateTest<1024>());
}
}
}
Template works with the 1024 switch case N: calls. Is there a way to have a helper / implementer instantiate all 1024 without the cases?
template <std::size_t N> List<String^>^ APIwrapper::UpdateTest() {
typedef char CHARX[N]; // N valid for 1 to 1024
CHARX vals[MAXFIELDS];
// NATIVE C++ VendorAPI(short, void*) vals is the address of the word aligned destination data
int count = VendorAPI(N, &vals);
List<String^>^ retList = gcnew List<String^>();
for (int c = 0; c < count; c++) {
CHARX temp;
strncpy(temp, vals[c], N); // \0 terminated char arrays
String^ x = gcnew String(temp);
retList->Add(x->Substring(0, N)->Trim());
}
return retList;
}
Following answer works for c++14, I don't know if it's compatible with cli.
You can use templates to generate a std::array
of function pointers:
using UpdateTestPtr = decltype(&UpdateTest<0>);
// Struct used to generate the array's content.
template<typename Sequence>
struct UpdateTestArrayImpl;
// Specialization used to get the values in the integer sequence.
template<std::size_t... indices>
struct UpdateTestArrayImpl<std::integer_sequence<std::size_t,indices...>> {
static constexpr std::array<UpdateTestPtr,sizeof...(indices)> value{UpdateTest<indices>...};
};
// Factorise sequence creation
template<std::size_t N>
using UpdateTestArray = UpdateTestArrayImpl<std::make_index_sequence<N>>;
static constexpr std::size_t N = 512;
// The array is needed at runtime. Create a normal (not constexpr) instance.
static std::array<UpdateTestPtr,N> functionArray = UpdateTestArray<N>::value;
And turn the switch/case
into an array lookup:
for each(int key in varList) {
allStrings->Add(key, functionArray[key]());
}
Live demo
Some compilers might produce a "template instantiation depth" error, depending on how make_integer_sequence
is implemented. The max limit of recursion depth can normally be increased with compiler options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With