constexpr对重载是否有用

时间:2015-10-17 23:37:52

标签: c++ constexpr

在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的情况,这不起作用?

3 个答案:

答案 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;
}