如何在C或C ++宏中使用函数作为文字字符串

时间:2013-10-07 10:53:57

标签: c++ macros

我发布了a similar question yesterday,该网站建议发布一个更好解释的新问题。

有两个宏:

#define COMPANY L"Test Company"
#define PRODUCT COMPANY L" in Canada"

PRODUCT的结果将是“加拿大的测试公司”。

现在,我们有以下要求:

  1. 使COMPANY成为“动态”字符串,调用函数返回公司名称,例如。 #define COMPANY getCompanyName()
  2. 我们不允许更改其他代码以引用公司,例如#define PRODUCT COMPANY L“in Canada”,因为代码中有如此多的宏
  3. 变更问题: PRODUCT的结果将是“测试公司”,丢失了“加拿大”字面部分。

    以下是代码:

    #include <stdio.h>
    #include <tchar.h>
    const wchar_t* getCompanyName() { return L"Test Company";};
    #define COMPANY getCompanyName();
    #define PRODUCT COMPANY L" in Canada"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    const wchar_t * company = COMPANY; // get Test Company
    const wchar_t * product = PRODUCT; // get Test Company in Canada
    
    wprintf(company);
    wprintf(product);
    
    
    return 0;
    } 
    

2 个答案:

答案 0 :(得分:2)

PRODUCT宏扩展为

getCompanyName(); L" in Canada"

所以

const wchar_t * product = getCompanyName(); L" in Canada";
wprintf(product);

打印

Test Company

正如所料。

在C ++中我们倾向于:

  • 避免使用宏(使用内联函数)
  • 避免裸指针(更喜欢STL设施)

所以,在C ++中我们更喜欢:

inline const std::wstring getCompanyName() { return L"Test Company";}
inline const std::wstring PRODUCT() { return getCompanyName() + L" in Canada";}

答案 1 :(得分:2)

这是一个讨厌的黑客,但它实际上是可能的。将COMPANY定义为以文字开头的表达式,以文字结尾,可以隐式转换为const wchar_t *

#define COMPANY L"" + getCompanyName() + L""

当然getCompanyName() 一定不能返回const wchar_t *,因为operator+没有为两个指针定义,而且无论如何它都适用于地址而不是字符串。

您基本上需要std::wstring,但您可能需要将其转换为const wchar_t *std::wstring不是。所以你必须定义自己的类:

struct AutoConvertibleString {
    std::string s;
    AutoConvertibleString(const std::string &s) : s(s) {}
    // C++ optimization for move:
    // AutoConvertibleString(std::string s) : s(std::move(s)) {}
    operator const wchar_t *() { return s.c_str(); }
};
AutoConvertibleString operator+(const wchar_t *l, const AutoConvertibleString &r) {
    return (l + r.s).c_str();
}
AutoConvertibleString operator+(const AutoConvertibleString &l, const wchar_t *r) {
    return (l.s + r).c_str();
}
// Ok, the operator+s could be optimized to use move for temporaries too...

AutoConvertibleString getCompanyName() { /* ... whatever ... */ }

这是一个丑陋的黑客。将所有这些转换为函数真的会更好。但它应该有用。