C++ Create BSTR at compile time / insert length into string at compile time?

倾然丶 夕夏残阳落幕 提交于 2019-12-24 01:24:39

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!