Reputation: 209
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
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
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
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