问题
Is it possible using macro magic or TMP to insert the length into a string at compile time?
For example:
const wchar_t* myString = L"Hello";
I would want the buffer to actually contain "[length] [string constant]".
I'm using MSVC 2010 which lacks constexpr. I figured there must be some trick to make this work as its possible to do:
const wchar_t* myString = L"\x005Hello";
My attempt so far:
template<int Size>
wchar_t* toBstr(const wchar_t* str)
{
#pragma pack(push)
#pragma pack(1)
struct BStr
{
int len;
wchar_t data[Size];
};
#pragma pack(pop)
static BStr ret;
ret.len = Size;
// don't want to have to copy here, how else could this work??
//ret.data = str;
return ret.data;
}
const wchar_t* m = toBstr<_countof(L"Hello")>(L"Hello");
This question seems related:
C++ template string concatenation
But not concat for two string constants, rather a constant generated from the length of the 2nd :)
回答1:
You cannot create a compile-time BSTR
. BSTR
are defined to be allocated by SysAllocString
and family. If it isn't it isn't a BSTR
, but an impostor.
However if the contents of the BSTR
is known at compile time, you can have a global BSTR
variable, and allocate it only once, avoiding the thousands of allocations you are concerned about.
I.e., have a variable declared as BSTR
, but initialize it to the string using SysAllocString
.
E.g.:
BSTR bsHello = SysAllocString(L"Hello");
回答2:
For BSTR
's which are transferred to functions only for reading, I use this simple macro:
#define DECLARE_BSTR(Variable, String)\
struct \
{ \
uint32_t uLength; \
OLECHAR szData[sizeof(String)]; \
} \
Variable = {sizeof(String) - sizeof(OLECHAR), String};
Example:
ITaskFolder *pTaskFolder;
DECLARE_BSTR(static bstrTaskFolderName, L"\\");
if (SUCCEEDED(pTaskService->GetFolder(bstrTaskFolderName.szData, &pTaskFolder)))
Variant which can be used in place of a BSTR
, i.e. without .szData
:
#define DECLARE_BSTR(Variable, String) \
struct \
{ \
uint32_t uLength; \
OLECHAR szData[sizeof(String)]; \
operator const OLECHAR *() const {return szData;}\
operator OLECHAR *() {return szData;}\
} \
Variable = {sizeof(String) - sizeof(OLECHAR), String};
Example:
ITaskFolder *pTaskFolder;
DECLARE_BSTR(static bstrTaskFolderName, L"\\");
if (SUCCEEDED(pTaskService->GetFolder(bstrTaskFolderName, &pTaskFolder)))
来源:https://stackoverflow.com/questions/20264616/c-create-bstr-at-compile-time-insert-length-into-string-at-compile-time