Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I want to define a helper templated struct inside a function. (Has to be inside the current function due to our own convention)
Why doesn't the following work? How do I fix it?
void foo() {
template<typename T>
struct MyHelper {
// ....
void func(int x, int y, ...) {
some_other<T>(...);
}
};
// Use MyHelper with different types.
if (some_logic) {
MyHelper<TypeA> helper;
helper.func(x, y, z);
} else if (some_other) {
MyHelper<TypeB> helper;
// ....
}
// ... more
// TypeA, TypeB, TypeC, ... don't share common parents.
}
Your convention is (in this case) not compatible with the C++ standard. Either define the struct outside of your function or specialize the struct "by hand", i.e. struct MyHelperInt, struct MyHelperDouble, ...
The latter approach is possible as you actually know what types to expect in your local function but it is obviously not a good option because of code duplication.
If the convention is not applicable then screw the convention. Seriously, conventions are not to be followed blindly. In this case the best the convention can do for you is to remind you that you are doing something which is uncommon in your work environment and that you should add a comment explaining why you decided to not follow the convention. Declare the helper outside of the function if you think this is the right thing to do.
However, as foo is not templated, I do assume that the types the Helper has to handle is from a limited set of types and that overloads would do as well:
void foo() {
struct MyHelper {
void func(TypeA, int x, int y) {
some_other<TypeA>(...);
}
void func(TypeB, int x, int y) {}
void func(TypeC, int x, int y) {}
};
MyHelper helper;
if (some_logic) {
helper.func(TypeA{},x, y);
} else if (some_other) {
helper.func(TypeB{},x, y);
// ....
}
If TypeA is nothing you want to create instances of on the fly, you could use tags instead to pick the right overload. However, from your usage it looks like you neither need templates nor overloads, but simple named functions would be fine:
void foo() {
struct MyHelper {
void funcA(int x, int y) {
some_other<TypeA>(...);
}
void funcB(int x, int y) {
some_other<TypeB>(...);
}
void funcC(int x, int y) {}
};
MyHelper helper;
if (some_logic) {
helper.funcA(x, y);
} else if (some_other) {
helper.funcB(x, y);
// ....
}
Templates and overloads enable great flexibility, but sometimes you just don't need that flexibility and simply using differently named functions is the much simpler alternative.
Related
Let's say I have a class which implements any number of similar methods, same return type and same parameter type to keep it simple.
Header:
protected:
void MoveForward(float Magnitude);
void MoveRight(float Magnitude);
Implementation:
void MyCharacter::MoveForward(float Magnitude) {
AddMovementInput(GetActorForwardVector() * Magnitude);
}
void Myharacter::MoveRight(float Magnitude) {
AddMovementInput(GetActorRightVector() * Magnitude);
}
Very similar methods, but only differing by the direction (Forward and Right in this case) in the method name, and the name of one of the internal functions.
What is the best way to abstract the common generic structure here?
You can do it in multiple ways, personally I've used an approach similar to the following:
enum class Direction { LEFT, RIGHT, TOP, BOTTOM };
class MyCharacter {
template<Direction DIR> Vector MyCharacter::getVector() const;
template<Direction DIR> void move() {
AddMovementInput(getVector<Dir>() * magnitude);
}
}
template<> Vector MyCharacter::getVector<Direction::LEFT>() const { ... }
template<> Vector MyCharacter::getVector<Direction::RIGHT>() const { ... }
Of course you can do the same exact thing without templates but I guess that you know what you are doing if you are specifically needing them.
Mind that you could directly pass the function as a template argument but I found it less clear, something like:
float GetActorForwardVector() { return 3.0f; }
class Foo
{
public:
template<float (*F)()> float move() { return F(); }
inline float moveLeft() { return move<GetActorForwardVector>(); }
};
int main()
{
Foo foo;
std::cout << foo.moveLeft();
}
To be honest you should not generalize at this level of algorithm. You just get a vector and scale it with a constant. If you were doing something more complex, then it would be another story. My first and foremost suggestion is let it stay this way.
Second, if you insist on generalization here it is (I assume GetXVector methods are class member):
class Foo
{
protected:
void MoveForward(float x) { Move(&Foo::GetActorForwardVector, x); }
void MoveRight(float x) { Move(&Foo::GetActorRightVector, x); }
private:
template<typename GetDirectionFunc>
void Move(GetDirectionFunc getDirection, float x)
{
AddMovementInput((this->*getDirection)() * x);
}
};
I prefer your original code.
You could use tag-dispatching.
Create the tag classes with same static member functions which implement the specific behavior:
namespace Direction {
struct Forward
{
static Vector actorVector() { return GetActorForwardVector(); }
};
struct Right
{
static Vector actorVector() { return GetActorRightVector(); }
};
} // namespace Direction
In your class, implement a template move function which takes an instance of the Direction class, but doesn't use it. Instead it calls the static member function of the tag class.
class MyCharacter
{
public:
template< typename Direction >
void move( const float magnitude, const Direction )
{
AddMovementInput( Direction::actorVector() * magnitude );
}
};
Usage example:
MyCharacter mc;
mc.move( 10.0, Direction::Forward() );
If you want to create more directions, only a new tag class is needed which implements the static member function.
Templates are not meant to be used when you handle different values (forward, right), they meant to handle different types (int, double).
You can use one generic Move function with arguments:
void Move(int x, int y);
// Move forward
Move (0, 1);
// Move right
Move (1, 0);
You can use function pointers to combine move direction and corresponding function in a struct:
struct MOVE_INFO
{
int x;
int y;
void (*GetVector)(void);
}
void Move(MOVE_INFO mv)
{
...
mv.GetVector();
...
}
main()
{
MOVE_INFO forward = {0, 1, SomeLib::GetForwardVector};
MOVE_INFO right = {1, 0, SomeLib::GetRightVector};
// Move Forward
Move(forward);
// Move Right
Move(right);
}
I have an existing code base with thousands of calls to foo(int bar[],int type) where in the function a number of structures are created where x[i].bar=bar[i] and x[i].type=type.
Now there's an edge case where I need to have different types for each x. So foo(int bar[], int type[]) leads to x[i].bar=bar[i] and x[i].type=type[i].
I currently have this implemented as an overload but that leads to a lot of copy pasted code. Is there a way to do this using templates?
You can make a third function, which is a "generalization" of the two. It should receive parameters of both "flavors", with a way to specify which flavor you want.
void foo_internal(int bar[], int type[], int default_type)
{
...
x[i].bar = bar[i];
x[i].type = (type == nullptr) ? default_type : type[i];
...
}
Put all your long code in there, then call it from both your overloads:
void foo(int bar[], int type[])
{
foo_internal(bar, type, 0);
}
void foo(int bar[], int type)
{
foo_internal(bar, nullptr, type);
}
Don't think the template could solve your problem, because a template function will be something like this
template<typename T>
void foo(int bar[],T type){
...
}
how do you manage to use type as int or int[] in generic way?
Instead you could refactor your code in order make foo(int bar[],int type) be used by foo(int bar[],int[] type), doing something like this
void foo(int bar[],int type)
{
...
}
void foo(int bar[],int[] type)
{
...
foo(bar,type[i]);
...
}
in this way, you should avoid to duplicate the code.
This question already has answers here:
is it possible to make function that will accept multiple data types for given argument?
(4 answers)
Closed 5 years ago.
I have some classes, named c1, c2, ... that all have a function in common named get_value().
now I want to write a function like this:
int foo(any_class_type obj){ return process(obj.get_value() ); }
how can I do this?
Writing a templated function might well do what you want:
template<typename any_class_type>
int foo(any_class_type obj){ return process(obj.get_value); }
You can either use a function template
template<typename T>
int foo(T const&obj)
{
return obj.getValue();
}
or use polymorphism:
struct C
{
virtual int getValue() const = 0;
};
struct C1 : C
{
int getValue() const override;
};
struct C2 : C
{
int getValue() const override;
};
int foo(C const&obj)
{
return obj.getValue();
}
or overload your function explicitly for the (some of the) types
int foo(C1 const&obj) { return obj.getValue(); }
int foo(C2 const&obj) { return obj.getValue(); }
or combine these approaches (when the best match will be picked).
A template allows unrelated object types and tends to generate more efficient code than polymorphic functions, but is header-only and also may result in cumbersome compiler error messages should you call it with an argument that does not have a fitting member getValue.
This question seems to have been asked numerous times before, for example here1, here2 and here3.
What I am trying to do is, set the member function of the C-Struct gsl_function to a member function of my class.
class MyClass{
double foo(double x)
{
return ...;
}
double bar(double x)
{
...
gsl_function F;
// Problem I cant do this (compiler error)
F.function = &(this->foo);
}
};
The third link above provides a solution, I think it is based on the wrapper approach described here4.
So my question is can I do better. Is there an easier way? For example, possibly by using Boost's function and Bind objects.
I am weighing up the option of using a gsl wrapper, such as o2scl. But am a bit releuctant as I may pay the price later if the wrapper is not well maintained. Any suggestions?
Since GSL allows you to pass in arbitrary parameters, you can abuse this to hold the pointer to the instance under question. Then use a static member function to forward to the member function:
class MyClass
{
double foo(double x)
{
...
}
static double foo_wrapper(double x, void *params)
{
return static_cast<MyClass*>(params)->foo(x);
}
double bar(double x)
{
...
gsl_function F;
F.function=&MyClass::foo_wrapper;
F.params=this;
// invoke GSL function passing in F
...
}
};
Can you do better? Is there an easier way? Not really. Any approach you take will be doing this under the covers somewhere.
But you can write a simple wrapper which hides some of this:
class gsl_function_pp : public gsl_function
{
public:
gsl_function_pp(boost::function<double(double)> const& func) : _func(func)
{
function=&gsl_function_pp::invoke;
params=this;
}
private:
boost::function<double(double)> _func;
static double invoke(double x, void *params)
{
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};
This should give you (possibly at a moderate performance penalty due to multiple indirections involved) the type of functionality you'd want:
class MyClass
{
double foo(double x)
{
...
}
double bar(double x)
{
gsl_function_pp F(boost::bind(&MyClass::foo, this, _1));
// invoke GSL function passing in F
...
}
};
The caveat is that you'll have to ensure that any gsl_function_pp object stays in scope for the entire time that the GSL might invoke it. So, don't try to set up a root finder/etc in one function (using a local gsl_function_pp), return, and then perform root finding iterations in another -- you'll get a crash or worse.
i have something like that
class Foo {
Bar a, b, c;
void doStuffWithA();
void doStuffWithB();
void doStuffWithC();
}
instead of writing an implementation for each of the methods i want something like a template. How to do that?
Cheers,
Dirk
Edit:
I explicitly need to know which variable I do stuff with (recursion):
class Foo {
Bar a, b, c;
Foo* parent;
static void doRecursiveStuffWithA(Foo *_node) {
if(_node->parent==NULL) {
return;
} else {
doRecursiveStuffWithA(_node->parent)
}
}
static void doRecursiveStuffWithB(Foo *_node) {
if(_node->parent==NULL) {
return;
} else {
doRecursiveStuffWithB(_node->parent)
}
}
static void doRecursiveStuffWithC(Foo *_node) {
if(_node->parent==NULL) {
return;
} else {
doRecursiveStuffWithC(_node->parent)
}
}
}
Edit2:
Maybe that does explain better what my problem is:
class Foo {
public:
int a, b, c;
}
class Bar {
public:
void doStuffWithAOfFoo(Foo *_foo);
void doStuffWithBOfFoo(Foo *_foo);
void doStuffWithCOfFoo(Foo *_foo);
}
I just want to keep my code simple and not to have to implement doStuffWithX three times...
I think you want parameters...
class Foo {
Bar a, b, c;
void doStuffWithBar(Bar x);
}
Templates are for dealing with a variety of data-types and function arguments are for dealing with a variety of variables.
#Andrew White has the simplest answer. If you want a function that can do the same thing but with a variety of different values, it should take an argument.
There are cases where we legitimately want different methods that look almost identical, like getFirstName(), setFirstName(), getLastName(), setLastName(). There, using arguments would rather defeat the purpose.
The architecture there is perfectly sound (and indeed widely accepted); the only problem is the tedium of typing it all up. If you just want to avoid all the extra typing, consider using an Integrated Development Environment that offers "code templates". Both Eclipse and Visual Studio (among many others, surely) will let you select a variable and click a button to generate a getter and setter for that variable. All the code with none of the hassle.
You can use a reference:
class Foo {
Bar a, b, c;
void doStuffWithBar(Bar& what)
{
print(what);
bool flag = check(what);
if (!flag)
doStuffWithBar(what);
}
}
You can use a pointer to member:
class Foo {
Bar a, b, c;
typedef Bar (Foo::*PointerToBar);
void doStuffWithBar(PointerToBar selector)
{
print(this->*selector);
bool flag = check(this->*selector);
if (!flag)
doStuffWithBar(selector);
}
}
The latter solution is more flexible: you can choose another object and/or another member with which to continue recursion (pointers to members are obscure and are rarely used; don't use them unless you need this flexibility):
class Foo {
Bar a, b, c;
Foo* next;
typedef Bar (Foo::*PointerToBar);
void doStuffWithBar(PointerToBar selector)
{
print(this->*selector);
if (next)
next->doStuffWithBar(selector);
}
}
Code smell - design problem? The repetition here makes it feels like Bar needs a new method:
void Bar::doStuff(Foo &foo);
Then you need to figure out what is public, private and const.
Edit: Your edit changes things a little. I now really feel that there are ways your design could be improved, e.g. STL container and algorithms.
To expand a little on Andrew's solutions, you might also be looking for:
void doStuffWithBar(Bar x, Bar y, Bar z);
If you actually have BarX x, BarY y and BarZ z, then you probably want to overload your member function in your class
class Foo {
BarX x;
BarY y;
BarZ z;
void doStuffWithBar(BarX x);
void doStuffWithBar(BarY y);
void doStuffWithBar(BarZ z);
};
You might also be looking for something like (this is the ugliest solution and I wouldn't really recommend it):
void doStuffWithBar(int n)
{
if(n==0)
doSomethingWithX();
else if(n==1)
doSomethingWithY();
else if(n==2)
doSomethingWithZ();
}
Edit:
ReturnType Bar::doStuffWithBar(ParamA a, ParamB b);