首页 > 解决方案 > 在 C++ 中将函数返回类型指定为模板参数

问题描述

我正在尝试为我的函数提供其模板参数的返回类型(以改进类型检查),这是一个函数引用。这是我到目前为止所尝试的:

#include <Windows.h>

模板 <类型名函数>
decltype(auto) proxyFunction(LPCSTR dllPath, LPCSTR functionName){
    自动 funcType = decltype(func);

    funcType funcPtr = (funcType) GetProcAddress(LoadLibraryA(dllPath), functionName);

    如果(函数指针)
        std::cout << "代理成功" << std::endl;
    别的
        std::cout << "代理失败" << std::endl;
    
    返回函数指针;
}

BOOL GetFileVersionInfoProxy(LPCSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData){
    auto getFileVersion = proxyFunction<GetFileVersionInfoProxy>("C:\\Windows\\System32\\Version.dll", "GetFileVersionInfoA");
    getFileVersion(lptstrFilename, dwHandle, dwLen, lpData);
}

但是,我收到以下编译时错误proxyFunction

没有函数模板的实例与参数列表参数类型匹配:(const char [32], const char [20])

我不太确定如何处理这个错误,因为它相当模糊。所以我想知道是否有人可以解释我的片段中的问题是什么?

PS 我正在使用带有 C++ 17 标准的 MS VS 2019,以防万一。

标签: c++functiontemplates

解决方案


你的func模板参数已经是你要返回的类型了,直接使用即可,不需要使用decltype(auto). 你的使用auto funcType = decltype(func);是完全错误的。

试试这个:

template <typename funcType>
funcType proxyFunction(LPCSTR dllPath, LPCSTR functionName)
{
    funcType funcPtr = (funcType) GetProcAddress(LoadLibraryA(dllPath), functionName);

    if (funcPtr)
        std::cout << "Proxy success" << std::endl;
    else
        std::cout << "Proxy fail" << std::endl;
    
    return funcPtr;
}

BOOL GetFileVersionInfoProxy(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData)
{
    using GetFileVersionInfoA_FuncType = BOOL (WINAPI *)(LPCSTR, DWORD, DWORD, LPVOID);

    auto getFileVersion = proxyFunction<GetFileVersionInfoA_FuncType>("C:\\Windows\\System32\\Version.dll", "GetFileVersionInfoA");
    if (getFileVersion)
        return getFileVersion(lptstrFilename, dwHandle, dwLen, lpData);

    return FALSE;
}

或者,如果让编译器为您推导出模板参数,则可以省略传递:

template <typename funcType>
bool proxyFunction(LPCSTR dllPath, LPCSTR functionName, funcType &funcPtr)
{
    funcPtr = (funcType) GetProcAddress(LoadLibraryA(dllPath), functionName);

    if (funcPtr)
        std::cout << "Proxy success" << std::endl;
    else
        std::cout << "Proxy fail" << std::endl;
    
    return (funcPtr != nullptr);
}

BOOL GetFileVersionInfoProxy(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData)
{
    using GetFileVersionInfoA_FuncType = BOOL (WINAPI *)(LPCSTR, DWORD, DWORD, LPVOID);

    GetFileVersionInfoA_FuncType getFileVersion;
    if (proxyFunction("C:\\Windows\\System32\\Version.dll", "GetFileVersionInfoA", getFileVersion))
        return getFileVersion(lptstrFilename, dwHandle, dwLen, lpData);

    return FALSE;
}

更新:根据@MooingDuck 的评论,看起来您实际上是在尝试将代理函数传递给模板,并让它推断出必要的参数和返回类型以用于 DLL 函数。如果是这样,请尝试更多类似的方法:

template <typename RetType, typename... ArgTypes>
struct proxyTraits
{
    using funcType = RetType (WINAPI *)(ArgTypes...);
};

template <typename RetType, typename... ArgTypes>
auto proxyFunction(
    LPCSTR dllPath,
    LPCSTR functionName,
    RetType (*proxy)(ArgTypes...))
{
    using funcType = typename proxyTraits<RetType, ArgTypes...>::funcType;
    funcType funcPtr = (funcType) GetProcAddress(LoadLibraryA(dllPath), functionName);

    if (funcPtr)
        std::cout << "Proxy success" << std::endl;
    else
        std::cout << "Proxy fail" << std::endl;
    
    return funcPtr;
}

BOOL GetFileVersionInfoProxy(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData)
{
    auto getFileVersion = proxyFunction("C:\\Windows\\System32\\Version.dll", "GetFileVersionInfoA", &GetFileVersionInfoProxy);
    if (getFileVersion)
        return getFileVersion(lptstrFilename, dwHandle, dwLen, lpData);

    return FALSE;
}

现场演示


推荐阅读