Reputation: 659
I have the following source code:
#include <functional>
#include <minwindef.h>
#include <winerror.h>
#include <libloaderapi.h>
#include <winreg.h>
namespace ffmock
{
/**
* @brief Primary template
*/
template<typename T>
struct function_traits;
/**
* @brief Template specialization for APIs
*/
template<typename RetType_t, typename... Args_t>
struct function_traits<RetType_t(Args_t...)>
{
using Ret_t = RetType_t;
using Sig_t = Ret_t(Args_t...);
using Ptr_t = Ret_t(*)(Args_t...);
using Api_t = std::function<Sig_t>;
};
template<typename RetType_t, typename API_t, RetType_t RetValue, DWORD Error2Set = NO_ERROR>
class
Mock
{
protected:
using Traits_t = function_traits<API_t>;
using Ret_t = typename Traits_t::Ret_t;
using Ptr_t = typename Traits_t::Ptr_t;
using Api_t = typename Traits_t::Api_t;
using Mock_t = Mock;
Mock(HMODULE Module, const char* ApiName);
template<typename... Args_t>
Ret_t operator()(Args_t&... Args);
};
} // namespace ffmock
#pragma warning(disable:4273) // inconsistent dll linkage
namespace Mocks
{
class FFRegCloseKey
: public ::ffmock::Mock<LSTATUS, decltype(::RegCloseKey), ERROR_INVALID_HANDLE>
{
friend
FFMOCK_IMPORT
LSTATUS
APIENTRY
::RegCloseKey(
_In_ HKEY Key
);
FFRegCloseKey(HMODULE Module) : Mock_t(Module, "RegCloseKey")
{
}
};
} // namespace Mocks
extern "C"
FFMOCK_IMPORT
LSTATUS
APIENTRY
RegCloseKey(HKEY Key)
{
static Mocks::FFRegCloseKey mock(LoadLibraryW(L"advapi32.dll"));
return mock(Key);
}
The program compiles cleanly with the 64-bit version of the Microsoft compiler. However, using the 32-bit version of the same compiler results in numerous errors. Here's the 64-bit compiler's output:
- Executing task: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe /nologo /Fodemo/bin/x64/ /std:c++17 /EHsc /D_DEBUG /D_AMD64_ /DWIN64 /D_UNICODE /DUNICODE /D_CONSOLE /DFFMOCK_IMPORT=__declspec(dllexport) /c C:\Play\ffmock\demo\tst\Test.cpp
Test.cpp * Press any key to close the terminal.
The 32-bit compiler's output:
- Executing task: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.38.33130/bin/Hostx86/x86/cl.exe /nologo /Fodemo/bin/x64/ /std:c++17 /EHsc /D_DEBUG /D_X86_ /DWIN32 /D_UNICODE /DUNICODE /D_CONSOLE /DFFMOCK_IMPORT=__declspec(dllexport) /c C:\Play\ffmock\demo\tst\Test.cpp
Test.cpp C:\Play\ffmock\demo\tst\Test.cpp(42): error C2027: use of undefined type 'ffmock::function_traits<API_t>' with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(41): note: see declaration of 'ffmock::function_traits<API_t>'
with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(42): note: the template instantiation context (the oldest one first) is C:\Play\ffmock\demo\tst\Test.cpp(64): note: see reference to class template instantiation 'ffmock::Mock<LSTATUS,LSTATUS (HKEY),6,0>' being compiled C:\Play\ffmock\demo\tst\Test.cpp(42): error C2061: syntax error: identifier 'Ret_t' C:\Play\ffmock\demo\tst\Test.cpp(43): error C2027: use of undefined type 'ffmock::function_traits<API_t>' with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(41): note: see declaration of 'ffmock::function_traits<API_t>'
with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(43): error C2061: syntax error: identifier 'Ptr_t' C:\Play\ffmock\demo\tst\Test.cpp(44): error C2027: use of undefined type 'ffmock::function_traits<API_t>' with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(41): note: see declaration of 'ffmock::function_traits<API_t>'
with [ API_t=LSTATUS (HKEY) ] C:\Play\ffmock\demo\tst\Test.cpp(44): error C2061: syntax error: identifier 'Api_t' C:\Play\ffmock\demo\tst\Test.cpp(50): error C2143: syntax error: missing ';' before '(' C:\Play\ffmock\demo\tst\Test.cpp(50): error C2238: unexpected token(s) preceding ';' C:\Play\ffmock\demo\tst\Test.cpp(50): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int C:\Play\ffmock\demo\tst\Test.cpp(50): error C2988: unrecognizable template declaration/definition C:\Play\ffmock\demo\tst\Test.cpp(50): error C2059: syntax error: '' C:\Play\ffmock\demo\tst\Test.cpp(92): error C3889: call to object of class type 'Mocks::FFRegCloseKey': no matching call operator found C:\Play\ffmock\demo\tst\Test.cpp(50): note: could be 'int ffmock::Mock<LSTATUS,LSTATUS (HKEY),6,0>::operator ()(Args_t &...)'
- The terminal process "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.38.33130\bin\Hostx86\x86\cl.exe '/nologo', '/Fodemo/bin/x64/', '/std:c++17', '/EHsc', '/D_DEBUG', '/D_X86_', '/DWIN32', '/D_UNICODE', '/DUNICODE', '/D_CONSOLE', '/DFFMOCK_IMPORT=__declspec(dllexport)', '/c', 'C:\Play\ffmock\demo\tst\Test.cpp'" terminated with exit code: 2. * Press any key to close the terminal.
Can anyone suggest how to fix these errors?
Upvotes: 0
Views: 86
Reputation: 659
Thank @igor-tandetnik for helping solve this issue.
There are two ways to solve this issue:
Once I added /Gz (__stdcall) to the command line, the code compiles.
Specialize the secondary template
template<typename RetType_t, typename... Args_t>
struct function_traits<RetType_t __stdcall(Args_t...)>
{
using Ret_t = RetType_t;
using Sig_t = Ret_t __stdcall(Args_t...);
using Ptr_t = Ret_t(__stdcall*)(Args_t...);
using Api_t = std::function<Sig_t>;
};
Upvotes: 0