Неверный аргумент для decltype - PullRequest
0 голосов
/ 29 мая 2018

Два дня назад я спросил о создании потоков для запуска нестатических методов классов с помощью 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);
}

Когда я пытаюсь скомпилировать приведенный выше код, я получаю:

ошибка 3556 'normalfunc': неверный аргумент для 'decltype'

Описание ошибки описано в MSDN:

Ошибка компилятора C3556

Тем не менее, я пробовал другой код до этого, и он прекрасно работает, но я не очень хорошо разбирался в синтаксисе:

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
}

Я знаю, этого кода достаточно, но яЯ хотел бы использовать Start(ltest) вместо Start<int,ltest>().

Примечание: никто не говорит, что я должен использовать функцию в качестве параметра в usualfunction, я использую ее как параметр шаблона, потому что CreateThread() не может передать функцию в качестве параметра.

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

, поскольку я использую Visual Studio 2015 и не могу использовать автоматические шаблоны, я использовал макросы, как сказал MM, и закончил этим

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
0 голосов
/ 29 мая 2018

с clang-cl 5 или 6 в 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;
}

это хорошо скомпилировано

0 голосов
/ 29 мая 2018

Параметры шаблона должны быть известны во время компиляции.Однако вы пытаетесь использовать нормальный параметр функции func в качестве аргумента шаблона.

Во втором коде вы задаете параметр шаблона в качестве аргумента шаблона, что нормально.

Ваш первый кодневерно по той же причине, что и этот код:

template<int X> void f() { }

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

, хотя сообщение об ошибке немного более неясно.


Начиная с C ++ 17 вы можете получить нужный синтаксис, выполнив эту модификацию для своего второго кода:

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

и назовите его как Start<ltest>();.

До C ++ 17 вы могли использовать макрос со вторым кодом:

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