Итак, я написал эту шаблонную переменную функцию ConcatBstr()
для объединения нескольких строк BSTR.
Однако другие пользователи вызывают его с аргументами других типов, кроме BSTR. Хотя эту функцию также можно использовать для приема WCHAR, другие типы строк в действительности не совместимы с ней.
Q1 : Как правильно ограничить тип аргументов, принимаемых ConcatBstr()
, только BSTR?
UINT LenSum() { // Stop condition
return 0;
}
template <typename T, typename... Args> // General case
UINT LenSum(T bstr, Args... args) {
return SysStringLen(bstr) + LenSum(args...);
}
void AppendBstr(WCHAR* dest) { // Stop condition
*dest = L'\0'; //Add the terminating zero. SysReAllocStringLen() allocated 1 more wchar_t for it already
}
template <typename T, typename... Args> // General case
void AppendBstr(WCHAR* dest, T src, Args... args) {
UINT n = SysStringLen(src);
wmemcpy(dest, BSTR(src), n);
AppendBstr(dest + n, args...);
}
BSTR ConcatBstr(BSTR* s) { return *s; }
template <typename... ADDTHIS>
BSTR ConcatBstr(BSTR* dest, ADDTHIS... addthis) {
UINT n = SysStringLen(*dest);
SysReAllocStringLen( dest, *dest, n + LenSum(addthis...) ); //Call this expensive function only ONCE !
AppendBstr( *dest + n, addthis...);
return *dest;
}
int main(int argc, char* argv[]) { //Usage
BSTR s1 = SysAllocString(L"Quick");
BSTR s2 = SysAllocString(L"Fox");
BSTR s3 = SysAllocString(L"Jumped");
BSTR s4 = SysAllocString(L"Over");
wcout << ConcatBstr(&s1, s2, s3, s4) << endl;
//I know that these BSTRs need to be freed eventually
}
Q2 : Можно ли улучшить этот код, сохранив свойство вызова SysReAllocStringLen()
только один раз?