Is constexpr useful for overload

后端 未结 3 2001
有刺的猬
有刺的猬 2021-01-21 23:52

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

相关标签:
3条回答
  • 2021-01-22 00:00

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

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

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

    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;
    }
    
    0 讨论(0)
  • 2021-01-22 00:22

    constexpr can only be applied to variables and functions, but not function parameters (details on cppreference). Furthermore, you cannot overload the function on whether it is computed at compile or run-time, i.e. this is not valid:

    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);
    }
    

    One way is to give the functions different names and call them accordingly.

    Just as a side note,

    A constexpr specifier used in a function declaration implies inline.

    So you don't need to declare your constexpr function inline

    Also, don't forget that constexpr functions are only guaranteed to be evaluated at compile-time if they are used in a context required at compile time. So to force it you would need to write:

     constexpr int a = Flip4('abcd');
    
    0 讨论(0)
  • 2021-01-22 00:26

    Your code is illegal.

    [C++11, dcl.constexpr] The constexpr specifier shall be applied only to the definition of a variable, the declaration of a function or function template, or the declaration of a static data member of a literal type (3.9). ... [ Note: Function parameters cannot be declared constexpr. — end note ]

    constexpr doesn't even exist in MSVC 2013, so you couldn't try it even if you wanted to. Also, if you're wondering why the feature isn't allowed, see constexpr overloading.

    0 讨论(0)
提交回复
热议问题