c++ - 使用宏的编译时条件类型操作

标签 c++ c++17

我正在尝试创建一个宏,根据参数的类型简化为某些内容。

为简单起见,我们称这些类型为 C 风格的字符串。这是情况:

int FunctionA( const char* input );
int FunctionB( const wchar_t* input );

#define Function( input ) \
    input is of type char \
        FunctionA( input ) \
    input is of type wchar_t \
        FunctionB( input )
// is there something else I can do to simplify this operation at compile time?
// maybe somehow use decltype( input ) to narrow which function to use?
// maybe if constexpr ( input ) or something? is there a constexpr version of the ?: operator?
// maybe std::is_same?

主要问题是这必须替换为可以作为参数传递的内容。分号不起作用。

例如

Foo( Function( "Example" ) );

使用 C++17 我有哪些选择?

最佳答案

第一种方法:

具有 typeid 比较的三元运算符。 &input[0] 是一个古老的 C 技巧,用于将 X 元素数组的类型衰减为指向类型的指针(我们也可以使用 input + 0)。 reinterpret_cast 用于在转换指针时消除警告/错误。

#define Function(input)  \
    ( \
        typeid(&input[0]) == typeid(const char*) || \
        typeid(&input[0]) == typeid(char*) \
    ) ? ( \
        FunctionA(reinterpret_cast<const char*>(input)) \
    ) : ( \
        typeid(&input[0]) == typeid(const wchar_t*) || \
        typeid(&input[0]) == typeid(wchar_t*) \
    ) ? ( \
        FunctionB(reinterpret_cast<const wchar_t*>(input)) \
    ) : ( \
        assert(0), \
        0 \
    )

void main1() {
    Foo(Function("Example"));
}

第二种方法:

具有专门实例化的模板:

template<typename T> inline int 
Function2(T t);
template<> inline int 
Function2<const char*>(const char* t) {
    return FunctionA(t);
}
template<> inline int 
Function2<const wchar_t*>(const wchar_t* t) {
    return FunctionB(t);
}

void main2() {
    Foo(Function2("Example"));
}

两个代码编译成:

        push    rax
        mov     edi, offset .L.str
        call    FunctionA(char const*)
        mov     edi, eax
        pop     rax
        jmp     Foo(int)   

将 clang 与 -O2 结合使用,如 godbolt 所示.但我想第一个对你的情况更安全。

关于c++ - 使用宏的编译时条件类型操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54611184/

相关文章:

c++ - 如何使用 visual studio 2015 rc 编译 7-zip

c++ - 从 C++ 中的类型列表获取类型索引

c++ - 内部for循环的上限是多少?

c++ - 如何在 C++ 中处理非常小的数字?

c++ - "using namespace"用于定义全局函数

c++ - C++ 中的链 optional

c++ - 使用 <experimental/filesystem> 和调用函数的链接器错误

c++ - 仅使用标准库设置文件创建时间

c++ - 使用 rundll32 运行 C++ DLL - 缺少条目

c++ - 使用模板函数对列表容器进行排序