如何正确组合类型的别名,功能指针和模板功能

How to correctly combine type aliases, function pointers, and template functions

本文关键字:功能 指针 别名 何正确 组合 类型      更新时间:2023-10-16

我在.h文件中声明以下类:

class BeliefCondFunc
{
private:
    using funcTypeBool = bool(*)(const bool&, const std::list<bool>&, const std::vector<bool>&);
    using funcTypeInt = bool(*)(const int&, const std::list<int>&, const std::vector<int>&);
    using funcTypeFloat = bool(*)(const float&, const std::list<float>&, const std::vector<float>&);
    using funcTypeString = bool(*)(const std::string&, const std::list<std::string>&, const std::vector<std::string>&);
    static std::unordered_map<std::string, funcTypeBool> const m_FunctionMapBool;
    static std::unordered_map<std::string, funcTypeInt> const m_FunctionMapInt;
    static std::unordered_map<std::string, funcTypeFloat> const m_FunctionMapFloat;
    static std::unordered_map<std::string, funcTypeString> const m_FunctionMapString;
    template <typename T>
    static bool Greater(const T& Fact, const std::list<T>& Facts, const std::vector<T>& Params)
    {
        return Params.empty() ? false : (Fact > Params[0]);
    }
public:
    template <typename T>
    static bool Call(const std::string FuncName, const T& Fact, const std::list<T>& Facts, const std::vector<T>& Params)
    {
        if(typeid(T) == typeid(int))
            return m_FunctionMapInt.find(FuncName) != m_FunctionMapInt.end() ? (*m_FunctionMapInt.at(FuncName))(Fact, Facts, Params) : false;
        return false;
    }
};

和.cpp文件中我定义了 const函数映射,例如:

std::unordered_map<std::string, BeliefCondFunc::funcTypeInt> const BeliefCondFunc::m_FunctionMapInt
{
    { "Greater", &Greater<int> },
};

但是,当我尝试编译此代码时,我会在Call()方法中获得以下错误:

中的函数指针。
error C2664: 'bool (const int &,const std::list<int,std::allocator<_Ty>> &,const std::vector<_Ty,std::allocator<_Ty>> &)': cannot convert argument 3 from 'const std::vector<std::string,std::allocator<_Ty>>' to 'const std::vector<int,std::allocator<_Ty>> &'*

有什么想法我在这里做错了什么?

正如Mikel F所述,问题在于,即使从未调用,if语句正文中的部分也必须编译。该语句是(从概念上)进行运行时检查,因此两个分支都必须在编译时有效。

解决此问题(只要您没有C 17编译器),您就可以编写两个版本:

  • 采用任何t并始终返回false
  • 的一般模板功能
  • T==int的专门版本将被召唤为INT,并在您的if语句的正文中使用方形:

示例*:

template <typename T>
static bool Call(const std::string FuncName, const T& Fact, const std::list<T>& Facts, const std::vector<T>& Params)
{
    return false;
}
template <>
static bool Call<int>(const std::string FuncName, const int& Fact, const std::list<int>& Facts, const std::vector<int>& Params)
{
    return m_FunctionMapInt.find(FuncName) != m_FunctionMapInt.end() ? (*m_FunctionMapInt.at(FuncName))(Fact, Facts, Params) : false;
}

*)我没有通过编译器将代码放置,因此它可能包含错别字。

您需要constexpr if。当您实例化每种类型的函数时,即使不是针对每种类型,它仍然尝试为模板中的每个语句创建代码。对于std::string

 if(typeid(std::string) == typeid(int))
            return m_FunctionMapInt.find(FuncName) != m_FunctionMapInt.end() ? (*m_FunctionMapInt.at(FuncName))(Fact, Facts, Params) : false;

会导致您的错误,因为您无法将std::string传递给整数映射函数。