【发布时间】:2015-10-17 23:37:52
【问题描述】:
C++ 中有没有办法根据输入的运行时/编译时常量调用不同的重载?我的 MSVC 版本 (12) 无法使用 constexpr 执行此操作。阅读 c++ 文档,我不确定这是否是 constexpr 的工作方式。
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
}
那么,如果可以做到这一点,该怎么做?我认为可能有一种方法可以使用模板推导来做到这一点,但我不知道怎么做。
编辑
我想出了这个,但不确定它为什么会起作用,&& 对我来说仍然很模糊,并且不确定这是否适用于所有事情。
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;
}
如果你编译时没有注释掉输出,它会产生这个输出。
run time
compile time
它会生成这个程序集,这就是我想要的:
int n = Flip4(argc);
000000013FA11270 bswap ecx
n += Flip4(1);
000000013FA11272 lea eax,[rcx+1000000h]
是否存在整数 T 不起作用的情况?
【问题讨论】:
-
不,没有
constexpr参数。 -
我该怎么做这样的事情。
-
如何将第一个“重载”改为
template <int n> inline int Flip4() { ... },然后用Flip4<0xc0de>()调用它? -
刚刚检查过 - 当您使用
_byteswap_ulong时,VS2015 也会在编译期间计算常量输入的值。所以一切都很好——根本不需要constexpr。我之前评论中链接中代码的程序集(但使用_byteswap_ulong而不是班次)是bswap ecx和lea eax,[rcx+64636261h]。 -
Clang 和最新版本的 GCC 应该在编译时计算这些值,并为
Flip4仅定义为constexpr的非 const 值发出bswap。根据@Rostislav 的说法,MSVC '15 也可以在编译时使用内在函数评估常量。