在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
}
如果可以这样做,怎么办?我认为可能有一种方法可以使用模板推导来实现它,但我无法弄清楚如何。
修改
我想出了这个,但我不确定它为什么会起作用,&amp;&amp;我仍然很生气,不确定这是否适用于所有事情。
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的情况,这不起作用?
答案 0 :(得分:2)
constexpr
只能应用于变量和函数,但不能应用于函数参数(cppreference的详细信息)。此外,您不能重置函数是关于它是在编译时还是在运行时计算,即这是无效的:
constexpr int Flip4(int n) {
return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
}
inline int Flip4(int n) {
return _byteswap_uint64(n);
}
一种方法是赋予函数不同的名称并相应地调用它们。
正如旁注,
函数声明中使用的
constexpr
说明符隐含inline
。
因此,您不需要声明constexpr
函数inline
另外,如果在编译时需要上下文中使用它们,请不要忘记constexpr
函数仅在保证在编译时进行评估。所以强迫它你需要写:
constexpr int a = Flip4('abcd');
答案 1 :(得分:1)
您的代码是非法的。
[C ++ 11,dcl.constexpr]
constexpr
说明符仅适用 变量的定义,函数的声明或 函数模板,或者静态数据成员的声明 字面类型(3.9)。 ... [注意:函数参数不能 宣布constexpr。 - 结束记录]
constexpr
甚至不存在于MSVC 2013中,因此即使您愿意,也无法尝试。另外,如果您想知道为什么不允许这项功能,请参阅constexpr overloading。
答案 2 :(得分:1)
要详细说明我的评论,您可以尝试以解决您所面临的限制:
的 Run It Online 强>
#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;
}
编辑:不要失去希望! User-defined literals来救援:)
的 Run It Online 强>
#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;
}