简体   繁体   中英

Incorrect argument to decltype

I asked two days ago about creating threads to run non-static class methods with the Win32 API, and I almost got a solution but there is something confusing me, so I'm asking this question before posting the answer in my previous question.

I'm trying to use this code to thread a function with an unknown return type:

template <class R, R func() >
unsigned int usualfunc() {
   func();
   return 1;
}

template <class R>
int Start(R(*func)()) {
   typedef decltype(&usualfunc<int, func>) D; // I get the error here , I can't get the address of the template function directly I need this
   D p = &usualfunc<R, func>;
   uintptr_t add = (uintptr_t)p;
   CreateThread(0, 0, (LPTHREAD_START_ROUTINE)add, 0, 0, 0);
   func();
   return 1;
}

int main() {
   Start(ltest);
}

When I try to compile the above code, I get :

error 3556 'usualfunc': incorrect argument to 'decltype'

The error description is described on MSDN:

Compiler Error C3556

However, I tried another code before this, and it works just fine, but I wasn't very good with the syntax:

template <class R, R func() >
unsigned int usualfunc() {
   func();
   return 1;
}

 template <class R,R func()>
int Start() {
   typedef decltype(&usualfunc<int, func>) D; // works well
   D p = &usualfunc<R, func>;
   uintptr_t add = (uintptr_t)p;
   CreateThread(0, 0, (LPTHREAD_START_ROUTINE)add, 0, 0, 0);
   func();
   return 1;
}

int main() {
   Start<int,ltest>(); // works
}

I know this code is enough, but I'd like to use Start(ltest) instead of Start<int,ltest>() .

Note: no one say that I should use the function as parameter in usualfunction , I'm using it as a template parameter because CreateThread() can't pass a function as a parameter.

Template parameters must be known at compile-time. However you attempt to use the normal function parameter func as a template argument.

In the second code you give a template parameter as the template argument, which is fine.

Your first code is wrong for a similar reason as this code:

template<int X> void f() { }

int main(int argc, char **argv) { f<argc>(); }

although the error message is a bit more obscure.


Since C++17 you can get the syntax you want by making this modification to your second code:

template <auto func>
int Start() {
    using R = decltype(func());
    // proceed as before...

and call it as Start<ltest>(); .

Prior to C++17 you could use a macro with your second code:

#define START(func) Start<decltype(func()), func>

as I'm using visual studio 2015 and can't use auto templates I used the macros as MM said and ended with this

Thread t;
t.SetFunc(ltest);
t.SetMember(testt, testf, tt); // class type , member function , pointer to class , it's like this : testt::testf , I can use this outside of class
t.SetMember(testt, testf, this); // from a member of the class , this is a pointer to the class , as I use this inside the member I can also thread private members here

with clang-cl 5 or 6 in visual studio 2015 :

template <auto func>
int Start() {
   using R = decltype(func());
   typedef decltype(&usualfunc<R, func>) D;
   D p = &usualfunc<R, func>;
   uintptr_t add = (uintptr_t)p;
   CreateThread(0, 0, (LPTHREAD_START_ROUTINE)add, 0, 0, 0);
   return 1;
}

this compiled well

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM