C++ decltype的参数不正确

C++ decltype的参数不正确,c++,templates,winapi,decltype,C++,Templates,Winapi,Decltype,两天前我问过关于创建线程来运行带有Win32 API的非静态类方法的问题,我几乎得到了一个解决方案,但有一些问题让我困惑,所以我在发布前一个问题的答案之前先问这个问题 我正在尝试使用此代码对具有未知返回类型的函数执行线程: template <class R, R func() > unsigned int usualfunc() { func(); return 1; } template <class R> int Start(R(*func)()) {

两天前我问过关于创建线程来运行带有Win32 API的非静态类方法的问题,我几乎得到了一个解决方案,但有一些问题让我困惑,所以我在发布前一个问题的答案之前先问这个问题

我正在尝试使用此代码对具有未知返回类型的函数执行线程:

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);
}
模板
unsigned int usualfunc(){
func();
返回1;
}
模板
int开始(R(*func)(){
typedef decltype(&usualfunc)D;//我在这里得到了错误,我不能直接得到模板函数的地址,我需要这个
dp=&usualfunc;
uintpttr_t add=(uintpttr_t)p;
CreateThread(0,0,(LPTHREAD\u START\u例程)add,0,0,0);
func();
返回1;
}
int main(){
启动(ltest);
}
当我尝试编译上述代码时,我得到:

错误3556“usualfunc”:对“decltype”的参数不正确

MSDN中描述了错误说明:

然而,在此之前我尝试了另一个代码,它工作得很好,但我对语法不是很好:

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
}
模板
unsigned int usualfunc(){
func();
返回1;
}
模板
int Start(){
typedef decltype(&usualfunc)D;//工作正常
dp=&usualfunc;
uintpttr_t add=(uintpttr_t)p;
CreateThread(0,0,(LPTHREAD\u START\u例程)add,0,0,0);
func();
返回1;
}
int main(){
Start();//有效
}
我知道这个代码已经足够了,但是我想使用
Start(ltest)
而不是
Start()


注意:没有人说我应该在
usualfunction
中将函数用作参数,我将它用作模板参数,因为
CreateThread()
无法将函数作为参数传递。

模板参数必须在编译时已知。但是,您尝试使用普通函数参数
func
作为模板参数

在第二段代码中,您提供了一个模板参数作为模板参数,这很好

您的第一个代码错误,原因与此代码类似:

template<int X> void f() { }

int main(int argc, char **argv) { f<argc>(); }
template void f(){}
intmain(intargc,char**argv){f();}
尽管错误信息有点模糊


从C++17开始,您可以通过对第二个代码进行以下修改来获得所需的语法:

template <auto func>
int Start() {
    using R = decltype(func());
    // proceed as before...
#define START(func) Start<decltype(func()), func>
模板
int Start(){
使用R=decltype(func());
//照旧进行。。。
并将其命名为
Start();

在C++17之前,您可以在第二个代码中使用宏:

template <auto func>
int Start() {
    using R = decltype(func());
    // proceed as before...
#define START(func) Start<decltype(func()), func>
#定义开始(func)开始

因为我使用的是visual studio 2015,无法使用自动模板,所以我使用了m.m所说的宏,并以此结束

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

在visual studio 2015中使用clang cl 5或6:

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;
}
模板
int Start(){
使用R=decltype(func());
typedef decltype(&usualfunc)D;
dp=&usualfunc;
uintpttr_t add=(uintpttr_t)p;
CreateThread(0,0,(LPTHREAD\u START\u例程)add,0,0,0);
返回1;
}

这个编译得很好

“但是语法不是很好”,在什么前提下?请编辑你的代码成为一个MCVEsorry我的英语不是很好,我的意思是写
Start();
Start(ltest)
更复杂,特别是当我与类成员一起使用它时,我当前的代码是这样工作的:
class testt{unsigned int testf(){….};testt*tt=new testt;Thread t;t.Set(tt)
我尝试过,但我正在使用的vs 2015不支持自动模板,并且在将其用作类成员时,宏不能作为选项。没有任何方法可以将函数参数用作类型吗?您仍然可以使用宏或只写出decltypeI我想将函数用作类的构造函数,但我不能,因为我无法不要在构造函数中使用模板参数,所以我使用它作为成员,它可以工作,但正如我所说的,问题只存在于函数的使用中,真的没什么好担心的。clang 6和5支持自动?如果是,我有clang cl 5,它应该可以做到it@dev65使用标志
-std=c++17