C ++在编译时创建BSTR /在编译时将长度插入字符串?

时间:2013-11-28 11:12:45

标签: c++ visual-c++ c++11 template-meta-programming bstr

是否可以使用宏魔术或TMP在编译时将长度插入字符串?

例如:

const wchar_t* myString = L"Hello";

我希望缓冲区实际上包含“[length] [string constant]”。

我正在使用缺少constexpr的MSVC 2010。我认为必须有一些技巧可以让这项工作成为可能:

const wchar_t* myString = L"\x005Hello";

到目前为止我的尝试:

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");

这个问题似乎有关:

C++ template string concatenation

但不是两个字符串常量的连续,而是从第二个长度生成的常量:)

2 个答案:

答案 0 :(得分:1)

您无法创建编译时BSTRBSTR被定义为由SysAllocString和家人分配。如果它不是BSTR,而是冒名顶替者。

但是,如果在编译时知道BSTR的内容,您可以拥有一个全局BSTR变量,并且只分配一次,避免您关注的数千个分配。

即,将变量声明为BSTR,但使用SysAllocString将其初始化为字符串。

E.g:

BSTR bsHello = SysAllocString(L"Hello");

答案 1 :(得分:1)

对于BSTR转移到仅用于阅读的函数,我使用这个简单的宏:

#define DECLARE_BSTR(Variable, String)\
struct                                \
{                                     \
    uint32_t uLength;                 \
    OLECHAR szData[sizeof(String)];   \
}                                     \
Variable = {sizeof(String) - sizeof(OLECHAR), String};

示例:

ITaskFolder *pTaskFolder;
DECLARE_BSTR(static bstrTaskFolderName, L"\\");
if (SUCCEEDED(pTaskService->GetFolder(bstrTaskFolderName.szData, &pTaskFolder)))

可用于代替BSTR的变体,即没有.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};

示例:

ITaskFolder *pTaskFolder;
DECLARE_BSTR(static bstrTaskFolderName, L"\\");
if (SUCCEEDED(pTaskService->GetFolder(bstrTaskFolderName, &pTaskFolder)))