通过std :: function传递成员函数

时间:2015-11-06 20:09:06

标签: c++ c++11 std-function

我想检查数据字段是否有效(有效意味着不为空且未填充默认值)

基本上

return (!connector->IsNull(field_id) and connector->Get<type>Default(field_id, default_value))

但“type”可以是多种类型之一(string,int64等...),因此有5-6种不同的函数。我为它做了一个辅助函数,我试图传递相关的GetDefault ...

template<typename T> bool IsValidField(std::unique_ptr<Connector>& connector, const std::function<T(int, T)> &GetDefault, int field_id, T default_value){
  return (!connector->IsNull(field_id) && connection->GetDefault(field_id, default_value) != default_value);
}

我正在调用辅助函数....

IsValidField(connector, connector->GetStringWithDefault,20,"")

我收到错误“错误:必须调用对非静态成员函数的引用 “因为GetStringWithDefault不是静态函数,我该如何解决这个问题?

或者,有没有办法让它稍微不那么尴尬?

3 个答案:

答案 0 :(得分:1)

两种可能的解决方案,一种是使用std::bind,另一种是使用std::mem_fn

对于使用std::bind的解决方案,它看起来像

template<typename T, typename F>
bool IsValidField(std::unique_ptr<Connector>& connector, F GetDefault,
                  int field_id, T default_value)
{
    return (!connector->IsNull(field_id) &&
            GetDefault(field_id, default_value) != default_value);
}

然后将其称为

IsValidField(

IsValidField(connector,
             std::bind(&ClassForConnector::GetStringWithDefault, _1, _2),
             20,"");

对于std::mem_fn解决方案,可能类似

template<typename T, typename F>
bool IsValidField(std::unique_ptr<Connector>& connector, F GetDefault,
                  int field_id, T default_value)
{
    return (!connector->IsNull(field_id) &&
            GetDefault(connector, field_id, default_value) != default_value);
}

并称之为

IsValidField(connector,
             std::mem_fn(&ClassForConnector::GetStringWithDefault),
             20,"");

答案 1 :(得分:1)

也许不是最整洁,但最简单的解决方案似乎是将所有东西都包装成lambda:

IsValidField(connector, [connector]() -> T {return connector->GetStringWithDefault(20, "")})

但是,您需要相应地调整IsValidField签名。

答案 2 :(得分:0)

这里有两件事。一次做一件事。

清理如何调用GetStringWithDefault,以便在不知道函数名称的情况下根据其类型获取某些内容,如下所示:

namespace impl {
  template<class T, T Connector::*Method(int, T const&)>
  struct GetWithDefault {
    T operator()(Connector const& connector, int id, T const& default) const {
      return (connector.*Method)(id, default);
  };
}

template<class T>
struct GetWithDefault;

template<>struct GetWithDefault<std::string>:
  impl::GetWithDefault<std::string, &Connector::GetStringWithDefault>
{};

重复每种支持的类型。现在,GetWithDefault<Bob>{}(*connector, id, default_bob)做你想做的事。

现在是null版本:

template<class T>
bool IsValidField(Connector const& connector, int id, T const& default_value) {
    return !connector.IsNull(id) && (GetWithDefault<T>{}(connector, id, default_value)!=default_value);
  }
};

这会将T和gettor之间的关联移动到帮助器类型GetWithDefault,我们通过显式特化(类似于特征类)来实现它。