将函数作为模板参数传递给类

时间:2020-02-14 08:30:11

标签: c++ templates

我想将函数作为模板参数传递,但是以某种方式我无法使其正常工作。过去,我已经写了很多模板类,但是只使用“普通”类型作为参数。我已经搜索了该问题,但似乎没有合适的解决方案。所以我被卡住了。

这是我要实现的目标: 我有几个要封装的类型特定的库函数。我知道也有其他方法可以做到这一点(例如继承),但是由于我也想在这里学一点点,因此我想使用模板方法来完成它。

我要实现的目标:

MyType<int> myIntObject(...);
...
int writeVal = 10;
myIntObject.Write(writeVal);
...
int readVal;
myIntObject.Read(&readVal);

也许也使用typedefs:

typedef MyType<int> MyIntType;

我到目前为止所做的事情:

template<typename T>
struct SetFunction
{
  inline ret_code operator()(someArgs, T value) const {return E_Fail;}
}

template<typename T>
struct GetFunction
{
  inline ret_code operator()(someArgs, T& value) const {return E_Fail;}
}

//template specialization:
template<>
struct SetFunction<int>
{
  inline ret_code operator()(someArgs, T value) const
  {
    //some other code
    return libraryFunctionWriteInt(someArgs, value);
  }
}

template<>
struct GetFunction<int>
{
  inline ret_code operator()(someArgs, T& value) const
  {
    //some other code
    return libraryFunctionReadInt(someArgs, &value);
  }
}
//do the specialization for all other types as well

template<class T, typename T_get_function = GetFunction<T>(), typename T_set_function = SetFunction<T>()>
MyType
{
public:
  MyType(someArgs)
  {
    if(T_get_function(someArgs, &_value) == E_Fail)
    {
      throw someting;
    }
  }

  bool SetValue(T value)
  {
    _value = value;
    //maybe some other code
    return T_set_function(someArgs, _value) == E_Success;
  }

  bool GetValue(T &value)
  {
    //maybe some other code
    return T_get_function(someArgs, &_value) == E_Success;
  }

private:
  T _value;
}

//and then eventually using it (maybe using some typedefs as well)
MyType<int> myIntObject(someArgs);
...
int writeVal = 10;
myIntObject.SetValue(writeValue);
...
int readVal;
myIntObject.GetValue(&readValue);

现在我得到编译错误:表达式列表在函数转换中被视为复合表达式,在我称为T_set_function / T_get_function的这两行中。我还尝试过直接将库函数作为模板参数传递,并且没有设置任何默认函数,但我也无法使其正常工作。

到目前为止,我几乎阅读的所有书籍,文章和示例都只处理传递“普通”类型作为模板参数,但是由于stl也使用传递函数,所以我真的很想知道如何做到这一点。

>

3 个答案:

答案 0 :(得分:1)

关于运算符的参数有一些不完整的代码,但是语法

template<class T, typename T_get_function = GetFunction<T>(), 
                  typename T_set_function = SetFunction<T>()>

不正确。 typename T_get_function =建议使用模板的类型参数,而=之后是表达式GetFunction<T>(),而不是声明符。

应该是

template<class T, typename T_get_function = GetFunction<T>, 
              typename T_set_function = SetFunction<T>>

然后,您不清楚T_get_function::operator()在没有类实例的情况下如何工作。应该是静态的,还是应该有一个实例。

template<class T, T_get_function getter = GetFunction<T>{}, 
              T_set_function setter = SetFunction<T>>{}
在这种特殊情况下,

typenameclass表示同一件事,在那儿并不需要。但是我们不知道那里是T_get_function吗?将其作为模板的类参数并分配默认类是C ++ 20功能。

Operator&返回指向变量的指针,您不能将其用作引用(也不需要这样做)。 该元代码包含几十个问题,从丢失到丢失;错误的语法以及缺少的关键字和声明。如果您在2020年之前专注于C ++标准,则应该从头开始重写它,否则请使用克劳斯的答案作为指导。

答案 1 :(得分:1)

我不知道是否抓住了您的问题,但是从标题上我读到您想将函数作为模板参数传递。即使您是否需要使用函数参数以及是否需要返回值,这也很容易。

示例:

template < auto func >
struct X
{   
    template < typename ... PARMS >
    static auto call(PARMS&& ... parms)
    {
        return func(parms...);
    }
};  

void func1()           { std::cout << "1" << std::endl; }
void func2(int value ) { std::cout << "2 with " << value << std::endl; }
int  func3()           { std::cout << "With retval" << std::endl; return 987; }

int main()
{   
    X<func1>::call( );
    X<func2>::call( 123 );
    std::cout << "Get retval" << X<func3>::call() << std::endl;
}   

答案 2 :(得分:1)

GetFunction<T>SetFunction<T>是仿函数,因此您需要一个实例来调用其call operator

您可以更换这些零件

  bool SetValue(T value)
  {
    _value = value;
    //maybe some other code
    return T_set_function{ /*Functor constructed*/ }(someArgs, _value) == E_Success;
  }

  bool GetValue(T &value)
  {
    //maybe some other code
    return T_get_function{ /*Functor constructed*/ }(someArgs, &_value) == E_Success;
  }

  if(T_get_function{ /*Functor constructed*/ }(someArgs, &_value) == E_Fail)
  {
    throw someting;
  }

正如@ Swift-FridayPie所说,您还需要重新安排模板参数部分。