2016-12-16 1 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 I определяют 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 :: Greater ' –

+0

@RichardHodges Нет, это ничего не меняет. – Matthias

+0

@AlexD Почему нет, и какой другой подход вы бы рекомендовали вместо этого? – Matthias

ответ

4

Как упоминалось в Mikel F, проблема заключается в том, что часть тела оператора if должна компилироваться, даже если она никогда не вызывается. Этот оператор (концептуально) проверяет время выполнения, поэтому обе ветви должны быть действительными во время компиляции.

Чтобы решить эту проблему (до тех пор, пока вы не C++ 17 компилятора доступен), вы можете написать две версию:

  • общая шаблонная функция, которая принимает любое T и всегда возвращает ложь
  • специализированная версия для 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

Смежные вопросы