2016-01-22 2 views
0

У меня есть следующий класс, используемый с MSVC2013 Update 4:Почему этот шаблон не компилируется?

template <typename T> 
class MyFunction; 

template<typename R, class... Ts> 
class MyFunction < R(Ts...) > 
{ 
public: 
    using func_type = R(*)(Ts...); 

    MyFunction(func_type f) 
     : m_func(f) 
    { 
    } 

    R operator()(Ts ... args) 
    { 
     return m_func(args...); 
    } 

private: 
    func_type m_func; 
}; 

Если я использую его следующим образом:

MyFunction<int (int)> f1(nullptr); 
MyFunction<int __cdecl(int)> f2(nullptr); 
MyFunction<int __stdcall(int)> f3(nullptr); 

Почему f3 не компилировать? (Учитывая, что __cdecl работает!).

error C2079: 'f3' uses undefined class 'MyFunction<int (int)>' 
error C2440: 'initializing' : cannot convert from 'nullptr' to 'int'  
+1

'nullptr = NULL'. Думаю об этом. –

+0

Конструктор принимает func_type, который является указателем на функцию, поэтому nullptr в порядке? – paulm

+0

Я подозреваю, что 'R (Ts ...)' неявно 'R __cdecl (Ts ...)', так что частичная специализация не соответствует 'int __stdcall (int)'. –

ответ

2

В MSVC соглашение о вызове является частью типа функции; соглашение о вызове по умолчанию - __cdecl, поэтому R(Ts...) действительно R __cdecl (Ts...) и не соответствует int __stdcall(int).

Если вы скомпилируете с /Gz, что делает соглашение по умолчанию __stdcall, вместо этого вы увидите ошибку на f2.

Вы должны написать частичные специализации для всех призывающих конвенций, которые вы хотите поддержать:

template<class F, class R, class... Args> 
class MyFunctionImpl { 
public: 
    using func_type = F*; 

    MyFunctionImpl(func_type f) 
     : m_func(f) 
    { 
    } 

    R operator()(Args ... args) 
    { 
     return m_func(args...); 
    } 

private: 
    func_type m_func; 
}; 

template<typename R, class... Ts> 
class MyFunction < R __cdecl(Ts...) > 
    : MyFunctionImpl<R __cdecl(Ts...), R, Ts...> { 
    using MyFunctionImpl<R __cdecl(Ts...), R, Ts...>::MyFunctionImpl; 
}; 

template<typename R, class... Ts> 
class MyFunction < R __stdcall(Ts...) > 
    : MyFunctionImpl<R __stdcall(Ts...), R, Ts...> { 
    using MyFunctionImpl<R __stdcall(Ts...), R, Ts...>::MyFunctionImpl; 
}; 

// etc. 
Смежные вопросы