Zhang
Zhang

Reputation: 3356

Pass an array (variable) as template argument

typedef int INT5[5] ;
    template<INT5 i5>
    void fun()
    {
        for (auto i : i5)
        {
            cout << i << endl;
        }
    }

    void test()
    {
        int i5[5] = { 2,3,1,2,4 };
        fun<i5>();//error
    }

I want to pass an array as a template argument, but failed.

error C2672: '__ExplicitVarTypeTest::fun': no matching overloaded function found

error C2971: '__ExplicitVarTypeTest::fun': template parameter 'i5': 'i5': a variable with non-static storage duration cannot be used as a non-type argument

Someone give me a solution to pass the varible as a fun's argument rather than the template's argument. But in my situation, I can't change the function's argument. because it's a callback function.

Actually, I need to do this

typedef char MyCharMap[UINT8_MAX];
    template<MyCharMap keymap>
    LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        //MSDN说了,nCode<0(HC_ACTION)的都用CallNextHookEx返回
        if (nCode >= HC_ACTION)
        {
            KBDLLHOOKSTRUCT* pStruct = (KBDLLHOOKSTRUCT*)lParam;
            if (keyMap[pStruct->vkCode])
            {
                switch (wParam)
                {
                case WM_KEYDOWN:
                    keybd_event(keyMap[pStruct->vkCode], 0, 0, 0);
                    break;
                case WM_KEYUP:
                    keybd_event(keyMap[pStruct->vkCode], 0, KEYEVENTF_KEYUP, 0);
                    break;
                default:
                    throw "other key event";
                }
            }
            return TRUE;
        }
        //传给系统中的下一个钩子   
        return CallNextHookEx(keyHook, nCode, wParam, lParam);
    }

SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc<keymap1>, theApp.m_hInstance, NULL);
SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc<keymap2>, theApp.m_hInstance, NULL);

Upvotes: 14

Views: 4145

Answers (1)

Brian Bi
Brian Bi

Reputation: 119562

Declaring a template to have a template parameter of type int[5] actually causes it to have a template parameter of type int*. This is similar to the decay that occurs in function signatures. To fix this, simply declare fun to take its array template argument by reference instead:

template<const INT5& i5> void fun();

You want to pass the array {2, 3, 1, 2, 4} as the template argument to fun. That's doable, but it has to obey the restrictions on glvalue constant expressions in [expr.const]/5 (C++17); it must refer to an object with static storage duration. Therefore, you should make i5 static:

static constexpr int i5[5] = { 2,3,1,2,4 };
fun<i5>();  // this should work

Upvotes: 22

Related Questions