2016-12-16 42 views
0

我有以下的类在我的.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>> &'* 

任何想法我在这里做错了吗?

+0

'&BeliefCondFunc ::大' –

+0

@RichardHodges不,不会改变任何事情。 – Matthias

+0

@AlexD为什么不,您会推荐什么其他方法? – Matthias

回答

4

由于米克尔˚F提到的,问题是,在if声明的身体部分具有编译,即使它永远不会被调用。该语句(概念上)是运行时检查,因此两个分支在编译时都必须有效。

为了解决这个问题(只要你没有一个C++编译器17提供),你可以写两个版本:

  • 一般模板函数,它接受任何T和始终返回false
  • 一个专门版本T==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; 
} 

*)我没有把代码经过编译器,所以它可能包含错别字。

+0

你的代码工作正常,非常感谢,这解决了我的问题 – Matthias

+0

@Matthias:欢迎您 – MikeMB

1

你需要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到整数地图功能。

+0

如何使用'constexpr if',它是在C++ 11可用? – Matthias

+0

@Matthias可悲的是,你需要C++ 17。 –

+0

恐怕是不是在我的情况选择:( – Matthias