问题描述
在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有用的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!