Andi
Andi

Reputation: 209

Pass function as template argument to a class

I want to pass functions as template arguments but somehow I can't get it to work. I've written a lot of template classes in the past but only using "normal" types as arguments. I've already searched for that issue but nothing seems to fit here. So I'm stuck.

Here is what I want to achieve: I have a couple of type specific library functions which I want to encapsulate. I know that there are other ways of doing it as well (e.g. inheritance) but since I also want to learn a little bit here, I want to get it done with the template approach.

What I want to achieve:

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

Maybe also using typedefs:

typedef MyType<int> MyIntType;

What I did so far:

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);

Now I get compile errors: expression list treated as compound expression in functional cast on those two lines where I call the T_set_function / T_get_function. I also tried passing the library functions directly as template arguments and don't set any default functions but I couldn't get it to work that way as well.

Almost all of the books, articles and examples I read so far are only dealing with passing "normal" types as template arguments but since stl makes use of passing functions as well I really want to know how to do this.

Upvotes: 0

Views: 89

Answers (3)

calynr
calynr

Reputation: 1282

GetFunction<T> and SetFunction<T> is a functor so you need an instance of it to call its call operator.

Could you replace these parts

  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;
  }

as @Swift-FridayPie said, you also need to re-arrange template parameters part.

Upvotes: 1

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14688

There is some incomplete code in regard to arguments of operator, but syntax

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

is incorrect. typename T_get_function = suggests a type parameter of template, while after = comes an expression GetFunction<T>(), not a declarator.

It should be

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

Then it's not clear how you expect T_get_function::operator() to work without instance of class. it's either should be static or you should have an instance.

template<class T, T_get_function getter = GetFunction<T>{}, 
              T_set_function setter = SetFunction<T>>{}

in this particular case typename and class mean same thing and is nt required there. But we don't know what T_get_function is here then? putting it as a class parameter of template and assigning default class is C++20 feature.

Operator & returns a pointer to variable, you can't use it as reference (and you don't need to do that). That metacode contains a several dozen problems ranging from missing ; to incorrect syntax and missing keywords and declarations. If you focus on C++ standard earlier than 2020, you ought to rewrite this from scratch, otherwise use Klaus's answer as guideline.

Upvotes: 1

Klaus
Klaus

Reputation: 25663

I don't know if I catch your question, but from the headline I read you want to pass a function as template parameter. That is quite easy, even if you want with function parms or not and with or without return value.

Example:

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;
}   

Upvotes: 1

Related Questions