I'm trying to build a tree-like structure in C++ and I found out about initializer_list and tried to implement it as part of my code. I want the code to be able to create an object from a set of properties, be able to apply some methods and then append at the end an array of children.
So I came up (after a lot of tries and failure) with this:
#include <vector>
#include <initializer_list>
struct Branch
{
// Branch properties
int val;
std::vector<Branch> data;
Branch(int i): val(i) {}
Branch& operator=(std::initializer_list<Branch> list)
{
data = list;
return *this;
}
// Some function with specific behaviour
Branch& bar() {
return *this;
}
};
int main()
{
auto Main = Branch(1).bar() = {
Branch(2) = {
Branch(4)
},
Branch(3).bar(),
};
return Main.val;
}
As you can see, in my code I first pass the int property and then (sometimes) call a function depending on whether I want some specific traits for that branch or not. Then I attach a list for its children.
Now, I know that there are probably many things wrong with my code. For once I wanted to pass "Branch&" as type to the initializer_list (and vector) so it does not create a copy but then the compiler said no operator "=" matches these operands inside the main function.
So, here is my question. Is there a way to solve this? Maybe a workaround to pass a reference... Or maybe another implementation with similar effects.
I also tried with std::array instead of vector but it seems like they are not compatible.
Related
Hoping for some clarification here. The code below executes fine, but when I uncomment that else statement a compilation error occurs. It's because in main I'm specifying a type int event though there's the possibility of type string. I've simplified my actual code to what's below to narrow down on the problem, what can I do to make it so that vector data in main can be of whatever type getNextLineOfData returns?
#include <vector>
using namespace std;
template< typename T>
std::vector<T> getNextLineOfData(bool someBoolean)
{
std::vector<T> data;
if (someBoolean)
{
data.push_back(1);
data.push_back(2);
data.push_back(3);
}
/*
else
{
data.push_back("1");
data.push_back("2");
data.push_back("3");
}
*/
return data;
};
int main()
{
vector<int> data = getNextLineOfData<int>(true);
return 0;
}
You are confusing compile time operations with runtime operations in your code snippet. When you template the function getNextLineOfData and instantiate it with getNextLineOfData<int>, the compiler goes ahead and generates a function that returns a vector for you. The if statement however is only evaluated at run time. So when the compiler tries to build your code it sees that you are adding both 1 and "1" to your vector<int> container based on the conditional. This is not allowed.
You could solve your problem with template specialization.
#include <vector>
using namespace std;
template<typename T>
std::vector<T> getNextLineOfData() {
// default
}
template<>
std::vector<int> getNextLineOfData()
{
std::vector<int> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
return data;
};
template<>
std::vector<std::string> getNextLineOfData()
{
std::vector<std::string> data;
data.push_back("1");
data.push_back("2");
data.push_back("3");
return data;
};
int main()
{
vector<int> data = getNextLineOfData<int>();
return 0;
}
EDIT: As #BobTFish points out, it might be better to overload the function rather than template specialize it. The solution above solves the problem the way you had it initially set up.
Reading from extra information in comments, I would suggest something like:
void getNextLine(std::vector<std::string>& output)
{
output.push_back("string data as you please");
}
void getNextLine(std::vector<int>& output)
{
output.push_back(1);
}
bool nextLineIsIntData()
{
// somehow determine if the coming data is strings or ints
return false;
}
int main()
{
std::vector<std::string> stringData;
std::vector<int> intData;
if (nextLineIsIntData())
getNextLine(intData);
else
getNextLine(stringData);
// do whatever you want
}
Well what you are doing is simply illegal. When you look at the if-else statement you say, well if some condition is true than this will execute but this won't, so it stands too reason that the compiler will ignore the part that is not executed. This is flat out wrong. What you need to do, which is layed out in previous answers is too overload or specialize the function for the different data types.
I should also mention that what you are trying to do is bad style. You are essentially relying on the user too pass the correct bool value, which influences the types you push_back() into the vector. Why do this when you have the power of template pattern matching at your disposal which completely removes the need to rely on correct user input.
In this case and any similar ones you come across it's much better to let the compiler decide
I am fairly new to c/c++ and I am trying to build a program for a genetic algorithm (using MS Visual Studio 2013). I will spare you the details of this program, but I do have a problem with 'passing parameters by reference'.
Can I pass on a parameter by reference to another function, inside a function? Hereunder you can find a simple example of my code.
struct solution{
int list1[100];
int list2[100];
int list3[100];
int list4[100];
};
void function1(solution& foo)
{
// Algorithm that fills list2
function2(foo); // Fills in list3
function3(foo); // Fills in list4
}
void function2(solution& foo)
{
// algorithm to fill in list3
}
void function3(solution& foo)
{
// algorithm to fill in list4
}
void localSearch(solution& foo)
{
for(int i = 0; i < 10; i++)
{
// Change a random value in list1 of foo
// Rerun function1 and see if it is a better solution
function1(foo);
}
}
int main()
{
solution bar;
// Fill list1 of bar randomly by other function
function1(bar);
// Output finished solution
return 0;
}
If I try to do this, I get all sorts of errors... Next to that, my solution struct gets corrupted and the first position in list1 randomly changes back to 0.
I tried several things to mitigate this, but nothing seems to work. If I just pass on the solution to function1 by value, the programs seems to run, but more slowly, because it has to copy this large struct.
So my questions are:
1) Is it possible to pass (by reference) on a parameter that was passed by reference to another function, in function1?
2) What would be a better solution?
1) Is it possible to pass (by reference) on a parameter that was passed by reference to another function, in function1?
Yes, it is possible to pass the same variable, by reference to another function.
void f1(My_Class& m); // Forward declaration.
void f2(My_Class& m);
void f1(My_Class& m) // Definition.
{
f2(m);
}
void f2(My_Class& m)
{
;
}
The forward declaration gives the compiler a "heads up" on how functions are to be used (their syntax). Without forward declarations, the compiler would get the knowledge from their definitions. However, the definitions or forward declarations must come before the function call.
2) What would be a better solution?
Here are some ideas to improve your solution:
1) Use std::vector instead of arrays.
2) Consider a std::vector of structures, rather than an a structure of arrays:
struct List_Record
{
int item1;
int item2;
int item3;
int item4;
};
std::vector<List_Record> My_Lists(100);
// or
List_Record My_Array[100];
Having the items in a structure or record allows better data cache management by the processor (all items in a row are placed contiguously).
3) Create a method in the structure for initialization.
You should have a constructor that loads the data items with a default value.
Consider adding a method that loads the data items from a file (very useful for testing).
I'm relatively new to programming and I did really well in my introductory class. However, as we are starting to get into the more advanced concepts of C++, I'm becoming more and more lost. I'm having a problem with a lab assignment, I hope you guys can help!
Write a generic list class called GenericList. The class should use a vector and be able to >be created with any type name. The class should have the following members:
A simple constructor
add(item) - add the item to the list
grabSmallest() - find, return and remove the smallest item in the list
Here is what I have so far, I believe it is at least set up correctly:
EDIT
This is what I have after the corrections that have been suggested, I've ran into a different problem now, though. Here is the revised code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template<typename T>
class GenericList
{
public:
GenericList();
void add(T value);
T grabSmallest();
private:
vector<T> listVector;
};
template<typename T>
GenericList<T>::GenericList()
{
}
template<typename T>
void GenericList<T>::add(T value)
{
listVector.push_back(value);
}
template<typename T>
T GenericList<T>::grabSmallest()
{
int smallest = listVector[0];
for (int i = 0; i < listVector.size(); i++)
{
if (listVector[i] < smallest)
{
smallest = listVector[i];
}
}
}
int main (){
GenericList<int> myList;
myList.add(10);
myList.add(5);
myList.add(20);
myList.add(15);
for(int i=0;i<4;i++)
cout << myList.grabSmallest() << " ";
}
I'm now having problems with my for loop in the grab function. Apparently, the compiler is putting random numbers into the vector.
Where is the last?
Even you have the last,
template<typename T>
void GenericList<T>::add(const T &value)
{
listVector[last++] = value; // <- should it be last++ or ++last?
}
or do you mean:
template<typename T>
void GenericList<T>::add(const T &value)
{
listVector.push_back(value)
}
BTW, With vector, you dont need the last field. It's kept in the vector: ` vector.size(). But why wrap vector when you could just use vector directly?
if you want the just want the smallest, priority_queue will do.
As gongzhitaao said, that line is not liking you because you never declare last and thus the compiler doesn't know what to do with it. as they said, you need to use push_back to solve that problem.
But you also need to solve another problem: what happens if they don't use int as their type? What if they want the "least" member of a custom class? You need to change this:
vector<int> listVector;
to this
vector<T> listVector;
So that the vector picks up the custom type that the template parameter T is specifying.
For grabSmallest I suggest you use some type of search to determine which element is the smallest, such as picking the first element, then looping through after that to see if each subsequent one is smaller or not. If it is, take that as your value, and loop. If not, just keep going. Whichever is left over at the end is smallest. But remember to use T as your type all the way through. Sorting it on every insert isn't necessary with this method.
As this is homework I didn't want to give you 100% of the answer with code, but hopefully the preceding paragraph is enough to get you going.
Edit: figured it out. Try www.codepad.org and run your code through it.
Basically, two errors in your grabSmallest() method.
It should be T smallest = listVector[0] not int. You should also have a "guard" that returns a default value (or throws an exception) if the list is empty.
grabSmallest() is supposed to return a value, but you forgot to. So your compiler is apparently way too forgiving, and didn't flag that as an error. Put return smallest as the last line of the method, just after the for loop.
Consider the following class member:
std::vector<sim_mob::Lane *> IncomingLanes_;
the above container shall store the pointer to some if my Lane objects. I don't want the subroutins using this variable as argument, to be able to modify Lane objects.
At the same time, I don't know where to put 'const' keyword that does not stop me from populating the container.
could you please help me with this?
thank you and regards
vahid
Edit:
Based on the answers i got so far(Many Thanks to them all) Suppose this sample:
#include <vector>
#include<iostream>
using namespace std;
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_)
{
a=a_;
}
void printLane()
{
std::cout << a << std::endl;
}
};
class B
{
public:
vector< Lane const *> IncomingLanes;
void addLane(Lane *l)
{
IncomingLanes.push_back(l);
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(&l1);
b.addLane(&l2);
b.IncomingLanes.at(1)->printLane();
b.IncomingLanes.at(1)->setA(12);
return 1;
}
What I meant was:
b.IncomingLanes.at(1)->printLane()
should work on IncomingLanes with no problem AND
b.IncomingLanes.at(1)->setA(12)
should not be allowed.(In th above example none of the two mentioned methods work!)
Beside solving the problem, I am loking for good programming practice also. So if you think there is a solution to the above problem but in a bad way, plase let us all know.
Thaks agian
A detour first: Use a smart pointer such shared_ptr and not raw pointers within your container. This would make your life a lot easy down the line.
Typically, what you are looking for is called design-const i.e. functions which do not modify their arguments. This, you achieve, by passing arguments via const-reference. Also, if it is a member function make the function const (i.e. this becomes const within the scope of this function and thus you cannot use this to write to the members).
Without knowing more about your class it would be difficult to advise you to use a container of const-references to lanes. That would make inserting lane objects difficult -- a one-time affair, possible only via initializer lists in the ctor(s).
A few must reads:
The whole of FAQ 18
Sutter on const-correctness
Edit: code sample:
#include <vector>
#include <iostream>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
#include <vector>
#include <iostream>
#include <memory>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_) // do you need this?
{
a=a_;
}
void printLane() const // design-const
{
std::cout << a << std::endl;
}
};
class B
{
// be consistent with namespace qualification
std::vector< Lane const * > IncomingLanes; // don't expose impl. details
public:
void addLane(Lane const& l) // who's responsible for freeing `l'?
{
IncomingLanes.push_back(&l); // would change
}
void printLane(size_t index) const
{
#ifdef _DEBUG
IncomingLanes.at( index )->printLane();
#else
IncomingLanes[ index ]->printLane();
#endif
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
//b.IncomingLanes.at(1)->printLane(); // this is bad
//b.IncomingLanes.at(1)->setA(12); // this is bad
b.printLane(1);
return 1;
}
Also, as Matthieu M. suggested:
shared ownership is more complicated because it becomes difficult to
tell who really owns the object and when it will be released (and
that's on top of the performance overhead). So unique_ptr should be
the default choice, and shared_ptr a last resort.
Note that unique_ptrs may require you to move them using std::move. I am updating the example to use pointer to const Lane (a simpler interface to get started with).
You can do it this way:
std::vector<const sim_mob::Lane *> IncomingLanes_;
Or this way:
std::vector<sim_mob::Lane const *> IncomingLanes_;
In C/C++, const typename * and typename const * are identical in meaning.
Updated to address updated question:
If really all you need to do is
b.IncomingLanes.at(1)->printLane()
then you just have to declare printLane like this:
void printLane() const // Tell compiler that printLane doesn't change this
{
std::cout << a << std::endl;
}
I suspect that you want the object to be able to modify the elements (i.e., you don't want the elements to truly be const). Instead, you want nonmember functions to only get read-only access to the std::vector (i.e., you want to prohibit changes from outside the object).
As such, I wouldn't put const anywhere on IncomingLanes_. Instead, I would expose IncomingLanes_ as a pair of std::vector<sim_mob::Lane *>::const_iterators (through methods called something like GetIncomingLanesBegin() and GetIncomingLanesEnd()).
you may declare it like:
std::vector<const sim_mob::Lane *> IncomingLanes_;
you will be able to add, or remove item from array, but you want be able to change item see bellow
IncomingLanes_.push_back(someLine); // Ok
IncomingLanes_[0] = someLine; //error
IncomingLanes_[0]->some_meber = someting; //error
IncomingLanes_.erase(IncomingLanes_.end()); //OK
IncomingLanes_[0]->nonConstMethod(); //error
If you don't want other routines to modify IncomingLanes, but you do want to be able to modify it yourself, just use const in the function declarations that you call.
Or if you don't have control over the functions, when they're external, don't give them access to IncomingLanes directly. Make IncomingLanes private and provide a const getter for it.
I don't think what you want is possible without making the pointers stored in the vector const as well.
const std::vector<sim_mob::Lane*> // means the vector is const, not the pointer within it
std::vector<const sim_mob::Lane*> // means no one can modify the data pointed at.
At best, the second version does what you want but you will have this construct throughout your code where ever you do want to modify the data:
const_cast<sim_mob::Lane*>(theVector[i])->non_const_method();
Have you considered a different class hierarchy where sim_mob::Lane's public interface is const and sim_mob::Really_Lane contains the non-const interfaces. Then users of the vector cannot be sure a "Lane" object is "real" without using dynamic_cast?
Before we get to const goodness, you should first use encapsulation.
Do not expose the vector to the external world, and it will become much easier.
A weak (*) encapsulation here is sufficient:
class B {
public:
std::vector<Lane> const& getIncomingLanes() const { return incomingLanes; }
void addLane(Lane l) { incomlingLanes.push_back(l); }
private:
std::vector<Lane> incomingLanes;
};
The above is simplissime, and yet achieves the goal:
clients of the class cannot modify the vector itself
clients of the class cannot modify the vector content (Lane instances)
and of course, the class can access the vector content fully and modify it at will.
Your new main routine becomes:
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
b.getIncomingLanes().at(1).printLane();
b.getIncomingLanes().at(1).setA(12); // expected-error\
// { passing ‘const Lane’ as ‘this’ argument of
// ‘void Lane::setA(int)’ discards qualifiers }
return 1;
}
(*) This is weak in the sense that even though the attribute itself is not exposed, because we give a reference to it to the external world in practice clients are not really shielded.
I'm trying create a class which adds functionality to a generic class, without directly interfacing with the wrapped class. A good example of this would be a smart pointer. Specifically, I'd like to create a wrapper which caches all the i/o for one (or any?) method invoked through the wrapper. Ideally, the cache wrapper have the following properties:
it would not require the wrapping class to be changed in any way (i.e. generic)
it would not require the wrapped class to be changed in any way (i.e. generic)
it would not change the interface or syntax for using the object significantly
For example, it would be really nice to use it like this:
CacheWrapper<NumberCruncher> crunchy;
...
// do some long and ugly calculation, caching method input/output
result = crunchy->calculate(input);
...
// no calculation, use cached result
result = crunchy->calculate(input);
although something goofy like this would be ok:
result = crunchy.dispatch (&NumberCruncher::calculate, input);
I feel like this should be possible in C++, although possibly with some syntactic gymnastics somewhere along the line.
Any ideas?
I think I have the answer you are seeking, or, at least, I almost do. It uses the dispatch style you suggested was goofy, but I think it meets the first two criteria you set forth, and more or less meets the third.
The wrapping class does not have to be modified at all.
It doesn't modify the wrapped class at all.
It only changes the syntax by introducing a dispatch function.
The basic idea is to create a template class, whose parameter is the class of the object to be wrapped, with a template dispatch method, whose parameters are the argument and return types of a member function. The dispatch method looks up the passed in member function pointer to see if it has been called before. If so, it retrieves the record of previous method arguments and calculated results to return the previously calculated value for the argument given to dispatch, or to calculate it if it is new.
Since what this wrapping class does is also called memoization, I've elected to call the template Memo because that is shorter to type than CacheWrapper and I'm starting to prefer shorter names in my old age.
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
// An anonymous namespace to hold a search predicate definition. Users of
// Memo don't need to know this implementation detail, so I keep it
// anonymous. I use a predicate to search a vector of pairs instead of a
// simple map because a map requires that operator< be defined for its key
// type, and operator< isn't defined for member function pointers, but
// operator== is.
namespace {
template <typename Type1, typename Type2>
class FirstEq {
FirstType value;
public:
typedef std::pair<Type1, Type2> ArgType;
FirstEq(Type1 t) : value(t) {}
bool operator()(const ArgType& rhs) const {
return value == rhs.first;
}
};
};
template <typename T>
class Memo {
// Typedef for a member function of T. The C++ standard allows casting a
// member function of a class with one signature to a type of another
// member function of the class with a possibly different signature. You
// aren't guaranteed to be able to call the member function after
// casting, but you can use the pointer for comparisons, which is all we
// need to do.
typedef void (T::*TMemFun)(void);
typedef std::vector< std::pair<TMemFun, void*> > FuncRecords;
T memoized;
FuncRecords funcCalls;
public:
Memo(T t) : memoized(t) {}
template <typename ReturnType, typename ArgType>
ReturnType dispatch(ReturnType (T::* memFun)(ArgType), ArgType arg) {
typedef std::map<ArgType, ReturnType> Record;
// Look up memFun in the record of previously invoked member
// functions. If this is the first invocation, create a new record.
typename FuncRecords::iterator recIter =
find_if(funcCalls.begin(),
funcCalls.end(),
FirstEq<TMemFun, void*>(
reinterpret_cast<TMemFun>(memFun)));
if (recIter == funcCalls.end()) {
funcCalls.push_back(
std::make_pair(reinterpret_cast<TMemFun>(memFun),
static_cast<void*>(new Record)));
recIter = --funcCalls.end();
}
// Get the record of previous arguments and return values.
// Find the previously calculated value, or calculate it if
// necessary.
Record* rec = static_cast<Record*>(
recIter->second);
typename Record::iterator callIter = rec->lower_bound(arg);
if (callIter == rec->end() || callIter->first != arg) {
callIter = rec->insert(callIter,
std::make_pair(arg,
(memoized.*memFun)(arg)));
}
return callIter->second;
}
};
Here is a simple test showing its use:
#include <iostream>
#include <sstream>
#include "Memo.h"
using namespace std;
struct C {
int three(int x) {
cout << "Called three(" << x << ")" << endl;
return 3;
}
double square(float x) {
cout << "Called square(" << x << ")" << endl;
return x * x;
}
};
int main(void) {
C c;
Memo<C> m(c);
cout << m.dispatch(&C::three, 1) << endl;
cout << m.dispatch(&C::three, 2) << endl;
cout << m.dispatch(&C::three, 1) << endl;
cout << m.dispatch(&C::three, 2) << endl;
cout << m.dispatch(&C::square, 2.3f) << endl;
cout << m.dispatch(&C::square, 2.3f) << endl;
return 0;
}
Which produces the following output on my system (MacOS 10.4.11 using g++ 4.0.1):
Called three(1)
3
Called three(2)
3
3
3
Called square(2.3)
5.29
5.29
NOTES
This only works for methods which take 1 argument and return a result. It doesn't work for methods which take 0 arguments, or 2, or 3, or more arguments. This shouldn't be a big problem, though. You can implement overloaded versions of dispatch which take different numbers of arguments up to some reasonable max. This is what the Boost Tuple library does. They implement tuples of up to 10 elements and assume most programmers don't need more than that.
The possibility of implementing multiple overloads for dispatch is why I used the FirstEq predicate template with the find_if algorithm instead of a simple for loop search. It is a little more code for a single use, but if you are going to do a similar search multiple times, it ends up being less code overall and less chance to get one of the loops subtlely wrong.
It doesn't work for methods returning nothing, i.e. void, but if the method doesn't return anything, then you don't need to cache the result!
It doesn't work for template member functions of the wrapped class because you need to pass an actual member function pointer to dispatch, and an un-instantiated template function doesn't have a pointer (yet). There may be a way around this, but I haven't tried much yet.
I haven't done much testing of this yet, so it may have some subtle (or not-so-subtle) problems.
I don't think a completely seamless solution which satisfies all your requirements with no change in syntax at all is possible in C++. (though I'd love to be proven wrong!) Hopefully this is close enough.
When I researched this answer, I got a lot of help from this very extensive write up on implementing member function delegates in C++. Anyone who wants to learn way more than they realized was possible to know about member function pointers should give that article a good read.
I don't think this can be easily done using just a wrapper as you'll have to intercept the IO calls, so wrapping a class would put the code at the wrong layer. In essence, you want to substitute the IO code underneath the object, but you're trying to do it from the top layer. If you're thinking of the code as an onion, you're trying to modify the outer skin in order to affect something two or three layers in; IMHO that suggests the design might need a rethink.
If the class that you're trying to wrap/modify this way does allow you to pass in the stream (or whatever IO mechanism you use), then substituting that one for a caching one would be the right thing to do; in essence that would be what you'd be trying to achieve with your wrapper as well.
It looks like a simple task, assuming the "NumberCruncher" has a known interface, let's say int operator(int).
Note that you'll need to make it more complicated to support other interfaces. In order to do so, i'm adding another template parameter, an Adaptor. Adaptor should convert some interface to a known interface. Here's simple and dumb implementation with static method, which is one way to do it. Also look what Functor is.
struct Adaptor1 {
static int invoke(Cached1 & c, int input) {
return(c.foo1(input));
}
};
struct Adaptor2 {
static int invoke(Cached2 & c, int input) {
return(c.foo2(input));
}
};
template class CacheWrapper<typename T, typeneame Adaptor>
{
private:
T m_cachedObj;
std::map<int, int> m_cache;
public:
// add c'tor here
int calculate(int input) {
std::map<int, int>::const_iterator it = m_cache.find(input);
if (it != m_cache.end()) {
return(it->second);
}
int res = Adaptor::invoke(m_cachedObj, input);
m_cache[input] = res;
return(res);
}
};
I think what you need is something like a proxy / decorator (design patterns). You can use templates if you don't need the dynamic part of those patterns. The point is that you need to well define the interface that you will need.
I haven't figured out the case for handling object methods, but I think I've got a good fix for regular functions
template <typename input_t, typename output_t>
class CacheWrapper
{
public:
CacheWrapper (boost::function<output_t (input_t)> f)
: _func(f)
{}
output_t operator() (const input_t& in)
{
if (in != input_)
{
input_ = in;
output_ = _func(in);
}
return output_;
}
private:
boost::function<output_t (input_t)> _func;
input_t input_;
output_t output_;
};
Which would be used as follows:
#include <iostream>
#include "CacheWrapper.h"
double squareit(double x)
{
std::cout << "computing" << std::endl;
return x*x;
}
int main (int argc, char** argv)
{
CacheWrapper<double,double> cached_squareit(squareit);
for (int i=0; i<10; i++)
{
std::cout << cached_squareit (10) << std::endl;
}
}
Any tips on how to get this to work for objects?