Shoot, now I have to look at the moon when I'm coding, thanks Narue.

You say it's a bad idea to overload pointers, which I get, but specifically pointers to Foo objects for the > operator, would that really be a bad idea you think?

Hey guys,

I know the title isn't possible, but I'd like to here how you'd do it then.

Suppose we have this code:
[code=cpp] Class Foo {public: int x; };

//somewhere in the code..

int main()
Foo one, two;
one.x = 10;
two.x = 20;

Foo *a = &one;
Foo *b = &two;

//We want to compare Foo::x here, not the pointers.
bool result = a > b;
return 0;

}
[/code]

How would you implement this? I've thought about a compare class, as the STL containers do, and ofcourse a compare functions, but I'd like to hear if there are other options, and if you pick compare classes over compare functions and why etc.

Here is the same problem in a small program, I still haven't figured it out why it thinks that set<ElementClass, CompareClass>::iterator is a value instead of a type.

[code=cpp]

include <iostream>

include <vector>

include <set>

using namespace std;

class IntCompare {
bool operator() (const int &a, const int &b){
return (a == b);
}

};

template <class ElementClass, class CompareClass>
class A {
public:
virtual void foo(const int &x){
pair< set<ElementClass, CompareClass>::iterator, bool> result;
}

set<ElementClass, CompareClass> elements;

};

/class B : public A<int, IntCompare> {
public:
virtual void foo(const int &x){
cout << x
x << endl;
}
};*/

int main (int argc, char * const argv[]) {
A<int, IntCompare> mySet;
for(int i = 0; i < 10; i++){
mySet.foo(10);
}

return 0;

}

[/code]

This code gives these compile errors:
[code]
main.cpp:17: error: type/value mismatch at argument 1 in template parameter list for 'template<class _T1, class _T2> struct std::pair'

main.cpp:17: error: expected a type, got 'std::__debug::set<ElementClass,CompareClass,std::allocator<_CharT> >::iterator'

main.cpp:17: error: invalid type in declaration before ';' token
[/code]

Hey guys,

I have this code snippet:
[code=cpp]
template <typename ElementType, typename CompareClass>
struct Delegate {
virtual bool geef(const ElementType &element){
pair <set<ElementType, CompareClass>::iterator, bool> ret; //this is line 196
ret = elements.insert(element); //197
return (ret.second); //198
}

virtual void output() = 0;

set<ElementType, CompareClass> elements;

};

struct ArtiestenPrinter : public Delegate<Lied, LiedCompare> {
virtual bool geef(const Lied &lied){
bool nieuwElement = Delegate<Lied, LiedCompare>::geef(lied); // 210
if (nieuwElement) {
cout << lied.artiest;
}
return nieuwElement;
}

virtual void output(){
    for(set<Lied, LiedCompare>::iterator it = elements.begin();
        it != elements.end();
        it++){

        cout << it->artiest << endl;
    }
}

};
[/code]

Which gives me these errors:
[code]
196: error: type/value mismatch at argument 1 in template parameter list for 'template<class _T1, class _T2> struct std::pair'
196: error: expected a type, got 'std::set<ElementType,CompareClass,std::allocator<_CharT> >::iterator'
196: error: invalid type in declaration before ';' token
198: error: request for member 'second' in 'ret', which is of non-class type 'int'
210: instantiated from here
197: error: cannot convert 'std::pair<std::_Rb_tree_const_iterator<Lied>, bool>' to 'int' in assignment
[/code]

I can't get my head around why the compiler is complaining, so any help is greatly appreciated.

Thanks in advance,

Nevermind.

OH err, the above was a question. xD

"Can you read files larger than 2^32 bytes in a 32 bit environment with streams?"

Say that's a regular int (assuming 4 bytes), you can't open files more than ~5GB in a 32-bit environment (since the stream can't be bigger than that).

Thanks for that though! I used MAX_INT before, but this is definitely better.

What wildgoose gives as a solution is called a "forward declaration", so you can read up about it (where what why how etc.)

And yes, Pancake stacks are most of the time FILO ones. xD ;)

Hey guys,

Can I tell istream to ignore ALL the characters until the delimiter char? It can be done with a loop but it's kinda weird I can't tell istream "discard until this char" imho, so maybe there's an hidden option somewhere.

Thanks in advance!

Hey, sorry to go offtopic anilopo, but Narue reminded me,

If I have a class like this:

[code=cpp]class X{
public:
X(int y) : y(y) {}

private:
int y;
}[/code]

Does the ctor invoke undefined behavior or is it valid C++? And does it do what I expect it to do: Set X::y to ctor param y? It works in MinGW GCC 3.4 afaik.

Again sorry for offtopic.

You can't call calc() in the product class. calc() isn't implemented in the Product class! ;)

What you're doing in the ctor is basically:

[code=cpp]
Product :: Product (...)
{
this->price = this->calc ();
}
[/code]

And since "this" in that context is a Product*, you can't call calc().

Hehe, I messed up the linking order.

Say that Program A depends on Lib B, and A and B contain references to Lib C, then A needs to supply B [B]before[/B] C, not after.

Hey guys,

So I have compiled my first home-written static library (named PixGUI) that happens to call OpenGL functions. However, I noticed that when compiling (using MinGWs GCC with Code::Blocks project set to "static library") it doesn't matter whether I supply the linker with libopengl32.a or not, it simply compiles each time.

However, when I link PixGUI to another project, i.e. Pixlings, and try to compile that, it gives me these errors:

[code]||=== Pixlings, Release ===|
..\PixGUI\lib\libPixGUI.a(button.o):button.cpp:(.text+0xc1)||undefined reference to glColor3fv@4'| ..\PixGUI\lib\libPixGUI.a(button.o):button.cpp:(.text+0xea)||undefined reference toglRectf@16'|
||=== Build finished: 2 errors, 0 warnings ===|
[/code]

The build log of libPixGUI.a (without supplying the linker with opengl32, but doesn't matter for undefined references)

[code]-------------- Build: Release in PixGUI ---------------

Compiling: element.cpp
Compiling: engine.cpp
Compiling: window.cpp
Compiling: button.cpp
Linking static library: lib\libPixGUI.a
ar.exe: creating lib\libPixGUI.a
Output size is 39.72 KB
Process terminated with status 0 (0 minutes, 2 seconds)
0 errors, 0 warnings[/code]

Build log of Pixlings

[code]
-------------- Build: Debug in Pixlings ---------------

Compiling: Program.cpp
Compiling: game.cpp
Compiling: main.cpp
Compiling: Menu.cpp
Linking console executable: bin\Debug\Pixlings.exe
..\PixGUI\lib\libPixGUI.a(button.o):button.cpp:(.text+0xc1): undefined reference to glColor3fv@4' ..\PixGUI\lib\libPixGUI.a(button.o):button.cpp:(.text+0xea): undefined reference toglRectf@16'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 1 seconds)
2 errors, 0 warnings[/code]

How would I solve these undefined references?

This might come in handy as well:

[url]http://www.cplusplus.com/reference/std/typeinfo/type_info/[/url]

Thanks Narue!

Hey guys,

Below code isn't working as I expect it to do. I expect it to read all params when 6 are given, buuuuuuuuuuuut it only reads one, the rest remains zero. It does enter the case, but the stringstream buf seems empty. What am I doing wrong?

[code=cpp]

include <iostream>

include <fstream>

include <sstream>

using namespace std;

define SCREAM cout << "OMAGAWD" << endl

int main(int argc, char *argv[])
{
// <src> <dest> [<offset> [<bytes, 0 = all> [<offset>]]
//writes bytes bytes from src+offset to dest+offset

size_t in_offset;
size_t bytes;
size_t out_offset;

in_offset = bytes = out_offset = 0;

stringstream buf;

switch (argc)
{
case 6:
SCREAM;
    buf.str(argv[5]);
    buf >> out_offset;

case 5:
SCREAM;
    buf.str(argv[4]);
    buf >> bytes;

case 4:
SCREAM;
    buf.str(argv[3]);
    buf >> in_offset;

default:
    ifstream in(argv[1], ios::binary);
    ofstream out(argv[2], ios::binary);
    break;
}

cout << "Writing from " << argv[1] << " + " << in_offset <<  " to " << argv[2] << " + " << out_offset << " for " << bytes << " bytes" << endl;

return 0;

}[/code]

Example params:

[icode]program.exe aap noot 1 2 3[/icode]

example output:

[code]OMAGAWD
OMAGAWD
OMAGAWD
Writing from aap + 0 to noot + 3 for 0 bytes[/code]

Thanks in advance,

Ugh, fixed it, I forgot the const. With normal functions the error messages are a lot clearer in GCC.. hope they "fix" this soon.

Here's the working code:
[code=cpp]//...
private:
template <typename T1, typename T2>
T2 &get_indexed(multimap<T1, T2> &container, const T1 &key, size_t index = 0) {
size_t count = container.count(key);
//...
[/code]

Hehe, back again. Templates are difficult if you're not precise I guess. I'm stuck on this one:

sss.hpp
[code=cpp] #include <string>

include <map>

include <stdexcept>

ifndef SSSHPP

define SSSHPP

namespace sss {
using namespace std;

class node {

public:
    multimap<string, string>  values;
    multimap<string, node>    children;

private:
    template <typename T1, typename T2>
    T2 &get_indexed(multimap<T1, T2> &container, T1 &key, size_t index = 0) {
        size_t count = container.count(key);

        if (count != 0 && count-1 >= index) {
            //it exists and index is within range
            //grab iterator, increment index times and return the node belonging to that.
            typename multimap<T1, T2>::iterator it = container.find(key);
            while (index--) it++;
            return it->second;
        } else {
            //Doesn't exist: throw OOR
            throw out_of_range((string)"get_indexed->"+"Element " + key + "doesn't exist!");
        }
    }
};

}

endif // SSSHPP

[/code]

Call with:

sss.cpp
[code=cpp]string &node::getValue(const string &name, size_t index) throw (out_of_range) {
get_indexed<string, string>(values, name, index);
}[/code]

Doesn't compile with:
[code]Code\SSSParser\sss.cpp In member function std::string& sss::node::getValue(const std::string&, size_t)': Code\SSSParser\sss.cpp error: no matching function for call tosss::node::get_indexed(std::multimap<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >&, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, size_t&)
[/code]

Ah, sorry. They are big functions. :) I finished the code and documented it, it's for review at my website, here's a quick link:

[url]www.dotsimplicity.net/?p=191[/url]

Thanks for your input! That typeid() will come in handy one day.

[quote=tux4life]Why are you using two separate functions read and write then ?[/quote]Because one reads and one writes? Hahahaha

I am not looking for a runtime solution, that's why I hadn't.

Here's a working example:
[code=cpp]
template <typename T>
bool read_or_write(const char *filename) {
T f(filename);
if (!f.good()) {
return false;
}

        bool success;
        if (typeid(T) == typeid(ofstream)) {
            success = write(f);
        } else if (typeid(T) == typeid(ifstream)) {
            success = read(f);
        }
        f.close();

        return success;
    }[/code]

But this way, I also have to define write(ifstream ... ), while I know 100% sure that the compiler will never have to call such a function. It kinda defeats it's use (making the code smaller) for this small function, but for bigger functions this sort of template is very usable I think.

Any compiler-time suggestions?

PS: For anyone reading this and thinking, why the hell are you creating such a function for 20 lines of code? It's because I'm not going to use read_or_write(), but would like to know how I'd accomplish maximum code re-usage in C++.

Oh I'm sure that doesn't work, never seen it, just made it up. But I want to know how I'd do that in C++. :D

Well, a design wouldn't need it. I don't know if its needed but can't you say something like: T can only be ifstream, ofstream

Code could look a bit like this:

[code=cpp]
template <typename T = {ifstream, ofstream}>
bool node::read_or_write(const char *filename) {
T f(filename);

if (!f.good()) {
    return false;
}

bool success;
if(T == typename ifstream){
    success = write(f);
} else if (T == typename ofstream){
    success = read(f);
}
f.close();

return success;

}
[/code]

Compiler should throw an error when you try to instantiate any other type of it.. I'm trying to create such a class now, but I'm not very good at it.

This is the best I could come up with, but I didn't compile/test it yet due to diner being ready.

[code=cpp]template <typename T>
class filestuffs {
filestuffs(const char *filename) : filename(filename) {
f(filename);
success = f.good();
success = read_or_write();
f.close();
}

//can't do this unless we know T
bool read_or_write(){ return false; }

T f;
bool success;
const char *filename;
const char [] errmsg = "Can't do this on anything but: ifstream, ofstream";

}
template <>
class filestuffs<ifstream> {
//now we know T! :D
bool read_or_write(){
return read(f);
}
}

template<>
class filestuffs<ofstream> {
bool read_or_write(){
return write(f);
}
}[/code]

Hey guys,

How would I partially specilize a template in a manner as below? Is that even possible?

I have these two functions:

[code=cpp]
bool node::read(const char *filename) {
ifstream f(filename);

if (!f.good()) return false;

bool success = read(f);
f.close();

return success;

}

bool node::write(const char *filename) {
ofstream f(filename);

if (!f.good()) {
    return false;
}

bool success = write(f);
f.close();

return success;

}
[/code]

And I'd like to create a function like this:

[code=cpp]
template <typename T>
bool node::read_or_write(const char *filename) {
T f(filename);

if (!f.good()) {
    return false;
}

bool success;
if(T == ifstream){
    success = write(f);
} else if (T == ofstream){
    success = read(f);
}
f.close();

return success;

}
[/code]

How would I do that?

Thanks in advance,

Okay dat was stoopid.

[code=cpp]node& node::child(const string name, size_t index) {
return searchInsert<string, node>(values, name, index);
}[/code]

Should of course be..
[code=cpp]node& node::child(const string name, size_t index) {
return searchInsert<string, node>(children, name, index);
}[/code]

No wonder.

Hey guys,

What am I doing wrong here?

sss.hpp
[code=cpp]

include <fstream>

include <string>

include <map>

namespace sss {
using namespace std;
class node {
public:
multimap<string, string> values;
multimap<string, node> children;

    string &value(const string name, size_t index = 0);
    node &child(const string name, size_t index = 0);

private:

    template <typename T1, typename T2>
    T2 &searchInsert(multimap<T1, T2> &container, const T1 &name, size_t index = 0) {
        typename multimap<T1, T2>::iterator it = container.find(name);

        //found none, insert...
        if (it == container.end()) {
            it = container.insert(pair<T1, T2>(name, T2()));
            return it->second;
        }

        //found one, multimap is sorted, iterate to index-th element or the end.
        for (size_t i = 0; i < index; i++) {
            it++;
            if (it == container.end()) {
                it = container.insert(pair<T1, T2>(name, T2()));
                return it->second;
            }
        }

        return it->second;
    }
};

}

[/code]

sss.cpp
[code=cpp]

include <iostream>

include <fstream>

include <map>

include <string>

include "sss.hpp"

using namespace std;
using sss::node;

string& node::value(const string name, size_t index) {
return searchInsert<string, string>(values, name, index);
}

node& node::child(const string name, size_t index) {
return searchInsert<string, node>(values, name, index);
}
[/code]

It won't compile with the following errors:

[code]
\Code\SSSParser\sss.cpp error: no matching function for call to `sss::node::searchInsert(std::multimap<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string> > >&, const std::string&, size_t&)'
[/code]

I don't really get what it's trying to do.

Thanks in advance,

Thanks guys, worked like a charm and I understand it too. woopiedoo.

Hey guys,

I have a class with a friend function and a member function with the same name. Calling the friend function from the member function gives me an error: it looks for <classname>::<function> while the friend function is of course simply <function>.

In this case, MinGW GCC says:

[code]
\Code\RationalNumber\rational.cpp | In member function long long unsigned int rational::gcd() const': \Code\RationalNumber\rational.cpp | error: no matching function for call torational::gcd(const long long unsigned int&, const long long unsigned int&) const'
\Code\RationalNumber\rational.cpp | note: candidates are: long long unsigned int rational::gcd() const
[/code]

How do I circumvent this naming collision without altering the function names? Can I tell the rational::gcd() to look for the other gcd without namespaces? Or with some sort of "not in any" namespace?

Here's the relevant code:

rational.hpp
[code=cpp]
class rational {
friend unsigned long long gcd(unsigned long long x, unsigned long long y);

public:
unsigned long long gcd() const;
};
[/code]

rational.cpp
[code=cpp]
unsigned long long gcd(unsigned long long x, unsigned long long y) {
if (x == y) return x;

//Euclidean method
unsigned long long diff;
while (x != 0 && y != 0) {
    if (x > y) {
        diff = x - y;
        x = diff;
    } else {
        diff = y - x;
        y = diff;
    }
}
return (x == 0) ? y : x;

}

unsigned long long rational::gcd() const {
return gcd(nominator, denominator);
}
[/code]

Thanks in Advance,
Nick

Sorry for those semi-gotos. Here are equivalent function without lazy-programmerness.

[code=cpp]
string& node::value(const string name, int index) {
using sss::value;

valueiterator it = values.find(name);
if (it == values.end()) {
    it = values.insert(value(name,string()));
    return it->second;
}

for (int i = 0; i < index; i++) {
    it++;
    if (it == values.end()) {
        it = values.insert(value(name,string()));
        return it->second;
    }
}

return it->second;

}

node& node::child(const string name, int index) {
using sss::child;

childiterator it = children.find(name);
if (it == children.end()) {
    it = children.insert(child(name, node()));
    return it->second;
}

for (int i = 0; i < index; i++) {
    it++;
    if (it == children.end()) {
        it = children.insert(child(name, node()));
        return it->second;
    }
}

return it->second;

}[/code]

PS:
In C I'd do something like this:

[code=cpp]#define nodeOrValue(returnType, type, plural, myIterator, insertType)\
returnType node::type(const string name, int index) {\
using sss::type;\
myIterator it = plural.find(name);\
if (it == plural.end()) {\
it = plural.insert(type(name, insertType()));\
return it->second;\
}\
for (int i = 0; i < index; i++) {\
it++;\
if (it == plural.end()) {\
it = plural.insert(type(name, insertType()));\
return it->second;\
}\
}\
return it->second;\
}

nodeOrValue(string&, value, values, valueiterator, string);
nodeOrValue(node&, child, children, childiterator, node);[/code]

So, considering this is (SPARTA!) C++, how should I do it? ;)

Hey guys,

With this defintion:

sss.hpp
[code=cpp]

include <fstream>

include <string>

include <map>

namespace sss {

using namespace std;

class node {
public:
    multimap<string, string>  values;
    multimap<string, node>    children;

    string &value(const string name, int index = 0);
    node &child(const string name, int index = 0);
    //...
};

typedef pair<string, string> value;
typedef pair<string, node>   child;

typedef multimap<string, string>::iterator valueiterator;
typedef multimap<string, node>::iterator   childiterator;

}[/code]

and this implementation:

sss.cpp
[code=cpp]#include <iostream>

include <fstream>

include <map>

include <string>

include "sss.hpp"

using namespace std;
using sss::node;
using sss::valueiterator;
using sss::childiterator;

string& node::value(const string name,int index) {
valueiterator it = values.find(name);
try {
int i;
if (it == values.end()) throw 0;
for (i = 0; i<index; i++) {
it++;
if (it == values.end()) throw 0;
}
} catch (int e) {
it = values.insert(sss::value(name,string()));
}
return it->second;
}

node& node::child(const string name,int index) {
childiterator it = children.find(name);
try {
int i;
if (it == children.end()) throw 0;
for (i = 0; i<index; i++) {
it++;
if (it == children.end()) throw 0;
}
} catch (int e) {
it = children.insert(sss::child(name, node()));
}
return it->second;
}[/code]

How would I merge these two functions? They have so much it common! It seemed redundant... Is there a way with templates and/or with a function that has the shared code?

Thanks in advance,