C++ database extension

Started by
6 comments, last by TangentZ 17 years, 7 months ago
What I would like to do is to extend C++ to do something like this:

class A{
  public:
  float x;
  float y;
  int z;
};
A a[1000];

A2 = Select(A).Where(x>3 && y<5 || z==10);
Which creates a new array from the old array where each member satisfies a[n].x>3 && a[n].y<5. So we introduce new commands such as "Where" which treat an array of classes like a database. Do you think it is possible to make such a command as this in C++? Could anyone suggest an example?
Advertisement
You might want to take a look at boost's lambda
You're not likely going to modify C++' syntax - in that case, why not design a programming/scripting language of your own? :)

Anyway, you could write a function that takes an array of A's and an expression and returns a new array. Now I think the parameter part is going to be the hardest to pull off here, giving minimum and maximum values for each member variabele might be sufficient but it means you'll need to write a different function for every other class you want this functionality for. You could write the function to accept a string containing the expression, but that solution is more complex, and still class-specific.
In other words, as far as I know, it's possible to write such functionality, but not in a templatized way - every new class requires a new version of the function to be written.

However, I'd like to know: why would you want this? For what situations do you intend to use this and what's the ultimate goal?
The reason I ask these questions is that there might be another, simpler or more effective, way to achieve what you need... :)
Create-ivity - a game development blog Mouseover for more information.
Quote:Original post by Captain P
You're not likely going to modify C++' syntax - in that case, why not design a programming/scripting language of your own? :)

No need. Select can return a Query object that will have a Where method that will accept a lambda function (see boost.lambda, as the AP suggested).

Quote:Original post by Captain P
However, I'd like to know: why would you want this? For what situations do you intend to use this and what's the ultimate goal?
The reason I ask these questions is that there might be another, simpler or more effective, way to achieve what you need... :)

Obviously, the goal is to have a simple embedded C++ query system. I actually think that this is a very good idea from a design point of view - and it can be quite effective. Now, I also happen to find code such as the OP's code incredibly easy to read (if the reader knows some tidy bits about lambda functions of course [smile]).

@paulbird: if you need more help to understand the concept of lambda functions, just ask to the boards - we'll be happy to help. Your idea is quite good.

Regards,
The reasons are the same reasons you would use a database language such as SQL. But instead you would apply this to arrays of classes in C++.

For example if I had an array of objects
class OBJECT{   public:   Color color;    float height;   float width;} objects[1000];

And I want to get an array of objects which are red and whose height is greater than 3. It would be useful to be able to simply write:
newobjects = Select(objects).where(color==Red && height>3)

or
newobjects = Select(objects).where(element.color==Red && element.height>3)

Then I want to double the widths of all thoses objects:
Select(newobjects).width*=2;

or
Select(newobjects).set(width=width*2);

for example.

PS

Yes it would be useful if someone could give an example of how do do something like this in Lambda functions, it might be interesting for other people too!
What you're after is basically what's called "filter" in functional languages. Maybe C++ implements it as part of its standard library?

Anyway, it's easy enough to implement, but I haven't done C++ in years, so consider this a naive example.

#include <list>#include <iostream>#include <iterator>#include <boost/lambda/lambda.hpp>using namespace boost::lambda;// This is your "where".template<typename Container, typename Predicate>void filter(Container const& orig, Container& result, Predicate p) {  typename Container::const_iterator it;  for(it = orig.begin(); it != orig.end(); ++it) {    if (p(*it)) {      result.push_back(*it);    }  }}int main() {  std::list<int> l1;  std::list<int> l2;  for(int i = 0; i < 10; ++i) {    l1.push_back(i);  }  // Filter (keep) items whose value is greater than 5.  // _1 > 5 is the lambda function.  filter(l1, l2, _1 > 5);  std::copy(l2.begin(), l2.end(), std::ostream_iterator<int>(std::cout, " "));  std::cout << std::endl;}


Hope this helps.
C++, even with boost::lambda, isn't terribly well suited for this kind of thing. If you need this kind of behavior, another language might be more appropriate.

The same thing in Ruby with comments for the non-rubyist:

class A    attr_accessor :x,:y,:z # allows non-class access to these variables    def initialize(x,y,z)        @x,@y,@z = x,y,z # @variable is used for member variables.    end    def to_s        "#{@x},#{@y},#{@z}" # describe how we want this to be printed out and whatnot.    endenda1 = [ A.new(1,2,3) , A.new(4,4,4) , A.new(5,6,7) , A.new(8,9,10) ]# original example arraya2 = a1.find_all { |a| (a.x > 3 && a.y < 5) || (a.z == 10) }# pretty self explanitory - returns a new array for which the block expression is true.a2.each { |a| puts a }# prints "4,4,4" and "8,9,10" on seperate lines


EDIT: Replaced that collect stuff with a simple .find_all, making it even easier :P

Of note: find_all is fairly mundane - it looks something like this:

class Array    def find_all( & block )        results = Array.new()        for i in 0..@length            if block(data)                results.push( data )            end        end    endend
Have you looked at Database Template Library? It doesn't quite do what you want (extend
the C++ syntax), but it sure makes C++ database programming much easier.
神はサイコロを振らない!

This topic is closed to new replies.

Advertisement