Пример кода для воспроизведения проблемы:
#include <iostream>
template< typename T, typename Func >
void action(Func T::* func)
{
T entry;
(entry.*func)();
}
struct A
{
void f()
{
std::cout << "A::f()" << std::endl;
}
};
int main()
{
action(&A::f);
return 0;
}
Этот код успешно компилируется с использованием MS VC ++ 2008, с VC ++ 2015 с использованием набора инструментов vc140, но не компилируется при использовании в проекте VC ++ 2015 с набором инструментов vc90 (VC ++ 2008). Дает странную диагностику
cpptest.cpp(20): error C2664: 'action' : cannot convert parameter 1 from 'void (__thiscall A::* )(void)' to 'void (A::* )(void)'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Кажется, компилятор теряет __thiscall, вызывая спецификатор соглашения при выводе типа для Func. Пытался принудительно указать __thiscall в разных частях кода, но безуспешно. Преобразование всего проекта в набор инструментов vc14 не является подходом из-за различных зависимостей, и сохранение его под VS 2008 маловероятно. Любые идеи, чтобы заставить компилятор понять такую конструкцию?
Изменение кода на
template< typename T, typename Func >
void action(Func func)
....
и призывая action< A >( &A::f );
работает, но выглядит немного некрасиво — я ожидаю, что компилятор сможет выводить тип для обоих аргументов шаблона (T и Func) автоматически
Задача ещё не решена.
Других решений пока нет …