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);
Related
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.
I've seen similar questions to this on SO but haven't found an answer for what I'm looking to do. I have two typedefs, only one of which will be used (other will be commented out):
typedef Student StudentType;
typedef StudentPF StudentType;
I want to use the alias StudentType for whichever one I'm currently using. Later on I have two different sets of code and I want to pick which set to run depending on whether StudentType is a Student or a StudentPF (Student taking course as Pass/Fail).
Is there a way to have something to this effect?
if (StudentType is of type StudentPF)
//do these things
else
//do these different things
The reason I'm attempting to do this is so I can change the behavior of my program just by simply commenting out one line and commenting in another if I keep the headers for both Student and StudentPF included.
Write a function template. Specialize it for each of the types you are interested in. Instantiate it with your typedef type.
template<typename T>
void DoStuff();
template<>
void DoStuff<Student>()
{
...
}
template<>
void DoStuff<StudentPF>()
{
...
}
int main()
{
DoStuff<StudentType>();
}
Obviously, Student and StudentPF aren't entirely interchangeable. So they ought to have something in their public interfaces letting you tell them apart. Maybe something like:
class Student {
public:
constexpr static bool is_pf = false;
// ...
};
class StudentPF {
public:
constexpr static bool is_pf = true;
// ...
};
void my_func() {
if (StudentType::is_pf)
;
}
But if you can't change Student or StudentPF, there's always:
#include <type_traits>
void my_func() {
if (std::is_same<StudentType, StudentPF>::value)
;
}
Neither of those will work if the code in the if or else clause won't compile for the "wrong" type. In that case, you would need some sort of static dispatch function.
You can use standard type traits for this :
if (std::is_same<StudentType, StudentPF>::value)
//do these things
else
//do these different things
I find it sometimes annoying that I have to initialise all POD-types manually. E.g.
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
I don't like this for several reasons:
I have to redo this in every constructor.
The initial value is at a different place than the variable declaration.
Sometimes the only reason I have to implement a constructor is because of this.
To overcome this, I try to use my own types instead. I.e. instead of using int x,y;, I use my own vector struct which also initialize automatically with 0. I also thought about just implementing some simple wrapper types, like:
template<typename T>
struct Num {
T num;
Num() : num(0) {}
operator T&() { return num; }
operator const T&() const { return num; }
T& operator=(T _n) { num = _n; return num; }
/* and all the other operators ... */
};
This basically solves this so far for all cases where I want to init with 0 (that are by far the most often cases for me).
Thanks to James McNellis for the hint: This can also be solved via the boost::value_initialized.
Now, not limited to POD-types:
But sometimes I want to initialise with something different and there are the troubles again because that Num template struct cannot easily be extended to allow that. Basically because I cannot pass floating point numbers (e.g. float) as a template parameter.
In Java, I would just do:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
I find it quite important that in such cases where you want to init a member variable always in the same way in all possible constructors, that you are able to write the init value directly next to the member variable, like in int x = 42;.
So the thing I was trying to solve is to do the same thing in C++.
To overcome the problem that I cannot pass the init-value via a template parameter, I hacked together an ugly macro:
#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )
/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
typedef T type; \
template<typename _T> \
struct Data { \
_T var; \
Data() : var(def) {} \
}; \
Data<T> data; \
T& operator=(const T& d) { return data.var = d; } \
operator const T&() const { return data.var; } \
operator T&() { return data.var; } \
}
(For other compilers, I can just omit that _LINENAME name for the struct and just leave it unnamed. But MSVC doesn't like that.)
This now works more or less like I want it. Now it would look like:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
While it does what I want (mostly), I still am not fully happy with it:
I don't like the name PIVar (which stands for PreInitVar) but I really couldn't come up with something better. At the same time, I want to have it short.
I don't like that macro hack.
How have you solved this? Any better solution?
There was an answer which was deleted again which said that C++0x allows basically the same syntax as in Java. Is that true? So then I would just have to wait for C++0x.
Please don't give any comments like:
"then just use Java instead" / "don't use C++ then" or
"if you need something like this, you are probably doing something wrong" or
"just don't do it this way".
Also, please don't tell me not to use it. I know about all the drawbacks of my current solution. Please only make comments about non-obvious drawbacks if you are really sure that I am not aware of that. Please don't just state that there are many drawbacks in my current solution. Please also don't state that it is not worse to use it. I am just asking if you know about a better solution than the one I have presented here.
Sometimes the only reason I have to implement a constructor is because of this.
You don't have to do that.
struct POD {
int i;
char ch;
};
POD uninitialized;
POD initialized = POD();
Equally in an initialization list:
class myclass
POD pod_;
// ....
myclass()
: pod_() // pod_'s members will be initialized
{
}
To overcome this, I try to use my own types instead.
Your type fails in this scenario:
void f(int&);
Num<int> i;
f(i);
There's likely more problems, but this is what occurred to me immediately.
How have you solved this? Any better solution?
Yes, we all have solved this. We did by not attempting to fight the language, but to use it the way it was created: initialize PODs in initialization lists. When I see this:
struct ML_LieroX : MapLoad {
std::string id;
PIVar(int, 0) type;
std::string themeName;
PIVar(int, 0) numObj;
PIVar(bool,false) isCTF;
I cringe. What is this doing? Why is it this way? Is this even C++?
All this just to save a few keystrokes typing an initialization list? Are you even serious?
Here's an old bon mot: A piece of code gets written once, but over its lifetime will be read tens, hundreds, or even thousands of times. That means that, in the long run, the time it takes to write a piece code is more or less neglectable. Even if it takes you ten times as long to write the proper constructors, but it saves me 10% of the time necessary to understand your code, then writing the constructors is what you should do.
Boost provides a value_initialized<T> template that can be used to ensure an object (POD or not) is value-initialized. Its documentation goes into great detail explaining the pros and cons of using it.
Your complaint about not being able to automatically initialize an object to a given value doesn't make much sense; that has nothing to do with the object being POD; if you want to initialize a non-POD type with a non-default value, you have to specify the value when you initialize it.
You could initialize POD structures as follows:
struct POD
{
int x;
float y;
};
int main()
{
POD a = {}; // initialized with zeroes
POD b = { 1, 5.0f }; // x = 1, y = 5.0f
return 0;
}
There is a proposal for C++0x which allows this:
struct A {
int x = 42;
};
That is exactly what I want.
If this proposal is not making it into the final version, the possibility of delegating constructors is another way of at least avoiding to recode the initialization in every single constructor (and at the same time avoiding a dummy helper function to do this).
In current C++, there does not seem to be any better way to do it despite what I have already demonstrated.
C++ does have constructor delegation, so why not use it?
struct AState
{
int x;
AState() : x(42) {}
};
class A : AState
{
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
};
Now initialization of x is delegated by all constructors. The base constructor can even accept arguments passed from each version of A::A.
Prior to C++0x there is a solution which works well if the non-zero value you want to initialize with is not completely arbitrary (which is usually the case in practice). Similar to boost::initialized_value but with an extra argument to take the initial value (which gets a little fussy because C++).
template<typename T> struct Default { T operator()() { return T(); } };
template<typename T, T (*F)()> struct Call { T operator()() { return F(); } };
template<int N> struct Integer { int operator()() { return N; } };
template< typename X, typename Value = Default<X> >
class initialized {
public:
initialized() : x(Value()()) {}
initialized(const X& x_) : x(x_) {}
const X& get() const { return x; }
operator const X&() const { return x; }
operator X&() { return x; }
private:
X x;
};
You might use it like this:
struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }
struct X {
initialized<int> a;
initialized<int, Integer<42> > b;
initialized<double> c;
initialized<double, Pi> d;
initialized<std::string> e;
initialized<std::string, Call<const char*, init_message> > f;
initialized<Point> g;
initialized<Point, Call<Point,top_middle> > h;
X() {}
};
I find the annoyance of having to create a dummy function to return any non-integral / non-default value is generally amortized across the entire library (since the non-zero initial values for a particular type are generally shared by many classes).
Obviously typedef is a friend here.
Anyway, can't wait to upgrade to C++0x/11/14/whatever.
Ok, it's been a while since I wrote in C++.
and I've never done anything quiet this high level.
So basically I need to create a class.
The constructor for the class needs to take a reference (or pointer) to a method form another class, or to a function.
Basically I have a class that needs to on occasion read a value from a fltk valuator (version 1.1.x), and then change some stuff about itself.
Each object will have it's own valuator associated with it.
(they also have a link to another object of the same parent, which after updating them selves from the valuator will tell to update, and so on)
So how do i pass functions around, in constructors?
Here is an example where a method of Foo is passed to the Bar constructor and later invoked on a given Bar object:
struct Foo
{
int z;
int add(int x, int y)
{
return x + y + z;
}
int mul(int x, int y)
{
return x * y * z;
}
};
typedef int (Foo::*foo_method)(int, int);
struct Bar
{
foo_method m;
Bar(foo_method m) : m(m) {}
int call_on(Foo* foo)
{
return (foo->*m)(4, 2);
}
};
int main()
{
Bar bar(&Foo::add);
Foo foo = { 123 };
bar.call_on(&foo);
}
If, on the other hand, you already know the Foo object at Bar construction time, then Bar does not really care which class the method belongs to. All it needs is a functor to call later, and the Foo object can simply be bound by the client.
#include <functional>
struct Bar
{
std::function<int (int, int)> f;
Bar(std::function<int (int, int)> f) : f(f) {}
int call()
{
return f(4, 2);
}
};
using namespace std::placeholders;
int main()
{
Foo foo = { 123 };
Bar bar(std::bind(&Foo::add, &foo, _1, _2));
bar.call();
}
If you don't have a C++0x compiler, replace std::bind with std::tr1::bind or boost::bind.
Your constructor might look something like this:
// convenient typedef. This is for a pointer to a function in Foo
// The function returns void and takes no parameters.
typedef void (Foo::*FooPtr)();
class Bar {
public:
Bar (FooPtr foo_ptr);
};
Check out some web references for more details on the syntax for pointer-to-members. It's a lot easier if you get familiar with it first.
As an additional note, check out the functions mem_fun and mem_fun_ref. These may do what you need.
The easiest way to capture this is with boost::function. It can store function pointers, but also the result of binding a member function to an object.
For instance,
class Foo {
Foo(boost::function<int(void)>);
};
will allow you to accept any source of integers.
I would like to know what is better to use in my situation and why. First of all I heard that using RTTI (typeid) is bad. Anyone could explain why? If I know exactly types what is wrong to compare them in a runtime? Furthermore is there any example how to use boost::type_of? I have found none searching through the mighty google :) Other solution for me is specialization, but I would neet to specialize at least 9 types of new method. Here is an example what I need:
I have this class
template<typename A, typename B, typename C>
class CFoo
{
void foo()
{
// Some chunk of code depends on old A type
}
}
So I need to rather check in typeid(what is I heard is BAD) and make these 3 realizations in example like:
void foo()
{
if (typeid(A) == typeid(CSomeClass)
// Do this chunk of code related to A type
else
if (typeid(B) == typeid(CSomeClass)
// Do this chunk of code related to B type
else
if (typeid(C) == typeid(CSomeClass)
// Do this chunk of code related to C type
}
So what is the best solution? I don't want to specialize for all A,B,C, because every type is has 3 specializations so I will get 9 methods or just this typeid check.
It's bad because
A, B and C are known at compile-time but you're using a runtime mechanism. If you invoke typeid the compiler will make sure to include metadata into the object files.
If you replace "Do this chunk of code related to A type" with actual code that makes use of CSomeClass's interface you'll see you won't be able to compile the code in case A!=CSomeClass and A having an incompatible interface. The compiler still tries to translate the code even though it is never run. (see example below)
What you normally do is factoring out the code into separate function templates or static member functions of classes that can be specialized.
Bad:
template<typename T>
void foo(T x) {
if (typeid(T)==typeid(int*)) {
*x = 23; // instantiation error: an int can't be dereferenced
} else {
cout << "haha\n";
}
}
int main() {
foo(42); // T=int --> instantiation error
}
Better:
template<typename T>
void foo(T x) {
cout << "haha\n";
}
void foo(int* x) {
*x = 23;
}
int main() {
foo(42); // fine, invokes foo<int>(int)
}
Cheers, s
Well generally solutions can be come up with without RTTI. It "can" show you haven't thought the design of the software out properly. THAT is bad. Sometimes RTTI can be a good thing though.
None-the-less there IS something odd in what you want to do. Could you not create an interim template designed something like as follows:
template< class T > class TypeWrapper
{
T t;
public:
void DoSomething()
{
}
};
then partially specialise for the functions you want to as follows:
template<> class TypeWrapper< CSomeClass >
{
CSomeClass c;
public:
void DoSomething()
{
c.DoThatThing();
}
};
Then in your class define above you would do something such as ...
template
class CFoo
{
TypeWrapper< A > a;
TypeWrapper< B > b;
TypeWrapper< C > c;
void foo()
{
a.DoSomething();
b.DoSomething();
c.DoSomething();
}
}
This way it only actually does something in the "DoSomething" call if it is going through the partially specialised template.
The problem lies in the code chunks you write for every specialization.
It doesn't matter if you write (lengthwise)
void foo()
{
if (typeid(A) == typeid(CSomeClass)
// Do this chunk of code related to A type
else
if (typeid(B) == typeid(CSomeClass)
// Do this chunk of code related to B type
else
if (typeid(C) == typeid(CSomeClass)
// Do this chunk of code related to C type
}
or
void foo()
{
A x;
foo_( x );
B y;
foo_( y );
C z;
foo_( z );
}
void foo_( CSomeClass1& ) {}
void foo_( CSomeClass2& ) {}
void foo_( CSomeClass3& ) {}
The upside of the second case is, when you add a class D, you get reminded by the compiler that there is an overload for foo_ missing which you have to write. This can be forgotten in the first variant.
I'm afraid this is not going to work in the first place. Those "chunks of code" have to be compilable even if the type is not CSomeClass.
I don't think type_of is going to help either (if it is the same as auto and decltype in C++0x).
I think you could extract those three chunks into separate functions and overload each for CSomeClass. (Edit: oh there are else if's. Then you might indeed need lots of overloads/specialization. What is this code for?)
Edit2: It appears that your code is hoping to do the equivalent of the following, where int is the special type:
#include <iostream>
template <class T>
bool one() {return false; }
template <>
bool one<int>() { std::cout << "one\n"; return true; }
template <class T>
bool two() {return false; }
template <>
bool two<int>() { std::cout << "two\n"; return true; }
template <class T>
bool three() {return false; }
template <>
bool three<int>() { std::cout << "three\n"; return true; }
template <class A, class B, class C>
struct X
{
void foo()
{
one<A>() || two<B>() || three<C>();
}
};
int main()
{
X<int, double, int>().foo(); //one
X<double, int, int>().foo(); //two
X<double, double, double>().foo(); //...
X<double, double, int>().foo(); //three
}
I think you've got your abstractions wrong somewhere.
I would try redefining A, B & C in terms of interfaces they need to expose (abstract base classes in C++ with pure virtual methods).
Templating allows basically duck-typing, but it sounds like CFoo knows too much about the A B & C classes.
typeid is bad because:
typeid can be expensive, bloats
binaries, carries around extra
information that shouldn't be
required.
Not all compilers support it
It's basically breaking the class hierarchy.
What I would recommend is refactoring: remove the templating, instead define interfaces for A, B & C, and make CFoo take those interfaces. That will force you to refactor the behaviour so the A, B & C are actually cohesive types.