是constexpr有用的重载 [英] Is constexpr useful for overload

查看:126
本文介绍了是constexpr有用的重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在c ++中有一种方法可以根据输入的运行时/编译时常数来获取不同的重载调用?我的版本(12)的MSVC不能这样使用constexpr。阅读c ++文档,我不知道这是否是constexpr工作原理。

Is there a way in c++ to get a different overload called based on the runtime/compile time constness of an input? My version(12) of MSVC can't do this using constexpr. Reading c++ documentation, I am not sure if this is the way constexpr works.

inline int Flip4(constexpr int n) {
    return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
}
inline int Flip4(int n) {
    return _byteswap_ulong(n);
}

int main(int argc, char* argv[]) {
    int a = Flip4('abcd');  // calc at compile time
    int b = Flip4(argc);  // calc at runtime
}

那么如果可以这样做,我认为可能有一种方式使用模板扣除来做到这一点,但我不知道如何。

So if this can be done, how? I think there might be a way to use template deduction to do it, but I can't figure out how.

编辑

我想出了这个,但不知道为什么它工作,&&

I came up with this, but am not sure why it works, && is still fuzy for me, and not sure if this works for everything.

template<class T> typename std::enable_if<std::is_arithmetic<T>::value, int>::type
inline Flip4(T&& n) {
    //cout << "compile time" << endl;
    return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
}
template<class T> typename std::enable_if<!std::is_arithmetic<T>::value, int>::type
inline Flip4(T&& n) {
    //cout << "run time" << endl;
    return _byteswap_ulong(n);
}

int main(int argc, char* argv[]) {
    int n = Flip4(argc);
    n += Flip4(1);
    return n;
}

如果编译时没有注释掉输出, p>

If you compile without commenting out the output, it produces this output.

run time
compile time

它生成这个程序集,这是我想要的:

and it produces this assembly, which is what I want:

int n = Flip4(argc);
000000013FA11270  bswap       ecx  
n += Flip4(1);
000000013FA11272  lea         eax,[rcx+1000000h] 

推荐答案

要详细说明我的意见,你可以尝试这个来解决你面对的限制:

To elaborate on my comment, you can try this to work around the limitation you're facing:

执行在线

#include <iostream>
using std::cout;
using std::endl;

template <int n>
constexpr int Flip4() {
    return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
}
inline int Flip4(int n) {
    return _byteswap_ulong(n);
}

int main() {
    constexpr int a = Flip4<0xabcd>();  // calc at compile time
    int b = Flip4(0xabcd);  // calc at runtime

    static_assert(a == -844431360, "");

    cout << "a: " << a << endl;
    cout << "b: " << b << endl;
}

EDIT :不要失去希望! 用户定义的文字可用于救援:)

EDIT: Don't lose hope! User-defined literals are here to the rescue :)

在线运行

#include <iostream>
using std::cout;
using std::endl;

// wraps a single integer (unsigned long long) in order to use it in a user-defined literal
// the type (unsigned long long) is a limitation of the standard: https://stackoverflow.com/a/16596909/865719
struct IntegerWrapper
{
    const unsigned long long value;
    constexpr explicit IntegerWrapper(unsigned long long val) : value{val} {}
};
// user-defined literal
constexpr IntegerWrapper operator "" _iw (const unsigned long long value) 
{ 
    return IntegerWrapper{value};
}

constexpr int Flip4(IntegerWrapper&& n) {
    return ((n.value & 0xFF) << 24) | ((n.value & 0xFF00) << 8) | ((n.value & 0xFF0000) >> 8) | ((n.value & 0xFF000000) >> 24);
}

inline int Flip4(int n) {
    return _byteswap_ulong(n);
}

int main() {

    constexpr int a = Flip4(0xabcd_iw);  // calc at compile time
    const     int b = Flip4(0xabcd);     // calc at runtime

    static_assert(a == -844431360, "");

    cout << "a: " << a << endl;
    cout << "b: " << b << endl;
}

这篇关于是constexpr有用的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆