• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

C++ Help?

Status
Not open for further replies.

poweld

Member
I agree with you, usea. Had the exact same argument with a friend of mine a few weeks ago after he read some smarmy article about how getters and setters are the bane of encapsulation. It's just not true.

Encapsulation is supposed to hide implementation for the benefit of extensibility. Even a simple class like Point could change drastically in the future, and any dependencies on exposed data will break if said data is removed or modified.
 
cpp_is_king said:
1) Don't make member functions with the same name as member variables. You have x() and x, this is ambiguous to the compiler.
Okay

2) You're writing point2.x, but you mean point2.x().
I did that and it didn't work

3) Why return const int? You're returning by value anyway, it's not like the receiver can modify the result.
Err that was one of the things I tried. Originally they didn't have const

Also, word of advice: Don't use encapsulation just to say you used it. If you have methods called getx() and setx() and all they do is return x; and x = param; then what's the point? Just expose them publicly in that case.

I don't want the receiver to be able to modify them so I made them private. I simply called the functions x() and y() because it's quicker than typing out getX() and getY(). I'll see if calling them simply x() and y() were what was causing the trouble because I already did everything else you suggested
 

Drkirby

Corporate Apologist
A quick question, when using a function for the condition for a For Loop, does it evaluate the function just once, or every iteration of the loop?

Like
Code:
for (i = 0; i < string.size; i++);
cout << "I is now " << i;
// </ Most useless use of a loop>
 

poweld

Member
Zoramon089 said:
Okay


I did that and it didn't work


Err that was one of the things I tried. Originally they didn't have const



I don't want the receiver to be able to modify them so I made them private. I simply called the functions x() and y() because it's quicker than typing out getX() and getY(). I'll see if calling them simply x() and y() were what was causing the trouble because I already did everything else you suggested
Please post your current code, as it seems you've made several changes since you last posted it.
 
poweld said:
Please post your current code, as it seems you've made several changes since you last posted it.

It works now. I'm guessing the problem was naming the function the same name as the variable...
 

poweld

Member
Zoramon089 said:
It works now. I'm guessing the problem was naming the function the same name as the variable...
Yes, that's a real issue as was stated before. Doing so means that if you have function x() and variable x, and try to pass x as an argument, the compiler will not know whether you wanted to pass the function pointer or the variable.

No two objects in the same scope should be named the same, and no two functions should have the same key (name + arguments) within the same scope*.

*Unless you are using virtual functions
 

Drkirby

Corporate Apologist
Zoe said:
^ every iteration
So it would be better to just to make a new variable, and assign it the value, assuming the value the function returns it is static throughout the loop, right?
 

Zoe

Member
Drkirby said:
So it would be better to just to make a new variable, and assign it the value, assuming the value the function returns it is static throughout the loop, right?

It's so trivial that it doesn't matter when you're talking about size() functions. I'm also pretty certain that the size is stored as a variable within the string class anyway.
 
Zoe said:
It's so trivial that it doesn't matter when you're talking about size() functions. I'm also pretty certain that the size is stored as a variable within the string class anyway.
For stl containers, this is right.

If you're using somebody else's code, you might want to cache that crap just to be on the safe side.
 
Elfforkusu said:
For stl containers, this is right.

Usually. The standard doesn't require a constant time implementation of list::size(), and indeed there are actual STL implementations that walk the entire list to compute the size.

std::basic_string (of which std::string is a particular template instantiation) is even not guaranteed by the standard to have constant complexity, although I think in every current implementation it does.
 

wolfmat

Confirmed Asshole
Elfforkusu said:
For stl containers, this is right.

If you're using somebody else's code, you might want to cache that crap just to be on the safe side.
Or you might NOT want to in some cases (like when for'd arrays shrink / grow while being walked through by design or something), doesn't look like this is one of them though, haha.
Still, not every for-loop is a foreach variant (most of them are, I suppose).
 

The Technomancer

card-carrying scientician
Okay, so this is just a general question. I know that technically you have to pass arrays into a function as references or pointers, and that modern compilers assume that so you don't have to actually explicitly state it. Thats why
Code:
 int function(int arr[], int size);
works just fine.

But why doesn't g++ like
Code:
 int function(int *arr[], int size);
or
Code:
 int & function(int arr[], int size);
 
The_Technomancer said:
Okay, so this is just a general question. I know that technically you have to pass arrays into a function as references or pointers, and that modern compilers assume that so you don't have to actually explicitly state it. Thats why
Code:
 int function(int arr[], int size);
works just fine.

But why doesn't g++ like
Code:
 int function(int *arr[], int size);
or
Code:
 int & function(int arr[], int size);


My question is what are you passing into this one.
Code:
int function(int *arr[], int size);

Code:
int main(int argc, char **argv)
{
   int array[5];

   function(&array, 1);

   return 0;
}

This would be a proper call to the function "function".

Code:
 int & function(int arr[], int size);

Requires that you return a reference to an integer (basically &arr[0]...&arr[n] or well to any memory location holding an integer that's not likely to go out of scope any time soon. Basically, it's fine as long as you don't return a reference to a local integer variable. )

Those two functions work in Visual C++, and I know from experience these both work on SCO compilers. Never tried anything like that on G++, but it should still work assuming you are returning something proper, or, in the case of the former, calling it with the correct parameters.
 

maharg

idspispopd
The_Technomancer said:
Okay, so this is just a general question. I know that technically you have to pass arrays into a function as references or pointers, and that modern compilers assume that so you don't have to actually explicitly state it. Thats why
Code:
 int function(int arr[], int size);
works just fine.

But why doesn't g++ like
Code:
 int function(int *arr[], int size);
or
Code:
 int & function(int arr[], int size);

Why do you think these don't work? It's quite likely they don't do exactly what you think they do, but there's nothing wrong with either of them grammatically or semantically.
 

Slavik81

Member
The_Technomancer said:
Okay, so this is just a general question. I know that technically you have to pass arrays into a function as references or pointers, and that modern compilers assume that so you don't have to actually explicitly state it. Thats why
Code:
 int function(int arr[], int size);
works just fine.

But why...
The answer is fuck arrays.

Avoid using raw arrays whenever possible.
Never use array notation when passing raw arrays into functions. Just use pointers to be less confusing.
Never use 2D arrays. Write a simple template class for them.
 
Slavik81 said:
The answer is fuck arrays.

Avoid using raw arrays whenever possible.
Never use array notation when passing raw arrays into functions. Just use pointers to be less confusing.
Never use 2D arrays. Write a simple template class for them.

What the fuck... I just... I don't even know what to say
 
Slavik81 said:
The answer is fuck arrays.

Avoid using raw arrays whenever possible.
Never use array notation when passing raw arrays into functions. Just use pointers to be less confusing.
Never use 2D arrays. Write a simple template class for them.
no, no, and no.
 

poweld

Member
Admittedly, arrays do kind of suck, and should likely be replaced with STL containers if you're working with C++ (if possible and makes sense to).

However, Slavik81, passing a pointer into a function strips away all meaning from the array, which implies a contiguous allocation of objects. A pointer simply means that there is a place in memory which may or may not contain an object of the pointer type, and certainly does not mean that the memory space of the pointer + sizeof(pointer_type) will contain another instance of the object. Even if you pass the size in, you are endangering your code down the line.

As for never using 2D arrays, again, I'd go with a templated 2D-vector-like class as you suggested if possible, but it's not as though arrays are evil.
 

bistromathics

facing a bright new dawn
Fuck, I just lost a big response I already typed, so this one will be shorter and less charming. You have to break them in early, though. Programmers, i mean.

Drkirby said:
A quick question, when using a function for the condition for a For Loop, does it evaluate the function just once, or every iteration of the loop?

Like
Code:
for (i = 0; i < string.size; i++);
cout << "I is now " << i;
// </ Most useless use of a loop>

format your code!
use curley braces. The reason for this is that it's very likely that you'll need to go back into that loop later. You can still keep it in a nice concise block if you want.

Code:
for (i = 0; i < string.size; i++) {
    cout << "hi gaf"; }

but then later, its easier to add comments or print statements or whatever you need . Also, dr. kirby, what you wrote wouldn't compile. You can't end a for statement with a semicolon. Formatting makes it easier to spot typos and quickly rule out potential fat-fingered mistakes before compile-time. Or after compile-time. Hell any time you can take stupidhands out of the disaster equation is a good time.



Drkirby said:
So it would be better to just to make a new variable, and assign it the value, assuming the value the function returns it is static throughout the loop, right?

scope!
Wait, first off, dude: don't throw the word static around like that! It means different things in different contexts and you're only going to confuse people or provoke people or maybe winsomely engage people. But it's all going to be ok because you have the right idea! Most languages will allow you to declare the i variable inline with the for statement!

Code:
int somenumber = 8;
for (int i=0; i < somenumber; i++)
{
     //[spoiler]comments![/spoiler]
    cout << "iteration: " << i << " of " << somenumber << "\n";
}

that variable i only exists within the scope of the for loop.

Stick with it. Software engineering is awesome engineering!
 

Slavik81

Member
cpp_is_king said:
What the fuck... I just... I don't even know what to say
Father_Mike said:
no, no, and no.
Unless you're working in very low level code, there are few reasons to use raw arrays in C++. They come with a bunch of gotchas, and are generally a pain to work with.

1. std::vector is often equally efficient, and provides much a simpler interface. It's easier to pass between functions, and provides fewer surprises. If you really do need behaviour more similar to a raw c-array, you can then use raw arrays, or templated versions which compile into identical code, but come with some helpful functionality, such as the length of the array built directly into the type.

2. On the occasions you need a multidimensional array, boost::multi_array provides similar benefits for +2D arrays.

3. A templated multidimensional array also solves the problem that functions must specify the dimensions of array they take (aside from the last dimension). They require that to compute the index. A templated array handles this nicely, removing that requirement if you so choose.

4. Using array notation to pass arrays between functions results in oddities. Arrays decay to pointers when you pass them between functions, so you might as well allow the code to reflect the actual state of the data structure. To do otherwise means someone is eventually going to be confused by this:
Code:
#include <iostream>
void function(int array[], int numElements)
{
   std::cout << "Now size is: " << sizeof(array) << endl;
}

void main()
{
   int array[5];
   std::cout << "Size is: " << sizeof(array) << endl;
   function(array, 5);
}
Code:
Output:
Size is: 20
Now size is: 4

Behavior is more sensible using pointer notation:
Code:
void function(int* array, int numElements)
{
   std::cout << "Now size is: " << sizeof(array) << endl;
}
Now it's clear why it prints 4.

If you'd like to explain why you should use raw arrays whenever possible, use array notation when passing raw arrays into functions, or use 2D arrays instead of simple template classes that compile into nearly identical code, I'd love to hear it.
 

Slavik81

Member
poweld said:
Admittedly, arrays do kind of suck, and should likely be replaced with STL containers if you're working with C++ (if possible and makes sense to).

However, Slavik81, passing a pointer into a function strips away all meaning from the array, which implies a contiguous allocation of objects. A pointer simply means that there is a place in memory which may or may not contain an object of the pointer type, and certainly does not mean that the memory space of the pointer + sizeof(pointer_type) will contain another instance of the object. Even if you pass the size in, you are endangering your code down the line.

As for never using 2D arrays, again, I'd go with a templated 2D-vector-like class as you suggested if possible, but it's not as though arrays are evil.
Array notation doesn't guarantee a contiguous allocation of objects. Or even that there will be an object.

For example,
int array[1]; // Only one element

or even,
function(NULL, 0); // No compile error
 

gblues

Banned
The_Technomancer said:
Okay, so this is just a general question. I know that technically you have to pass arrays into a function as references or pointers, and that modern compilers assume that so you don't have to actually explicitly state it. Thats why
Code:
 int function(int arr[], int size);
works just fine.

But why doesn't g++ like
Code:
 int function(int *arr[], int size);
or
Code:
 int & function(int arr[], int size);

Code:
int function(int arr[], int size)

This function accepts a reference to an array (or, a pointer to an element in an array) and an integer size parameter.

Code:
int function(int *arr[], int size)

This function accepts a pointer to a reference to an array (or, a pointer to a pointer to an element in an array), and an integer size parameter.

Code:
int& function(int arr[], int size)

This function accepts a reference to an array (or, a pointer to an element in an array) and an integer size parameter, and returns a reference to an integer.

None of these are at all equivalent to each other.
 

Chichikov

Member
Generally, when passing a conceptual array, a pointer works best as it leaves maximum flexibility to the caller as far as data structure go (which is why I don't like using stl types there too; but I don't like stl in general).

That does not make the whole concept of an array bad.
And your assertion is so broad that I'm not sure where to even begin.

Do you want like a list of cases where it's an invaluable tool?
 

Slavik81

Member
Chichikov said:
Generally, when passing a conceptual array, a pointer works best as it leaves maximum flexibility to the caller as far as data structure go (which is why I don't like using stl types there too; but I don't like stl in general).

That does not make the whole concept of an array bad.
And your assertion is so broad that I'm not sure where to even begin.

Do you want like a list of cases where it's an invaluable tool?
Ok. Perhaps I was a bit overdramatic.

Arrays are one of the most complex and confusing parts of C++. Particularly multidimensional arrays. Beginners should beware, and carefully consider alternatives first. There are reasons not to use templated replacements, such as compatibility and compile times, but for most purposes there are more suitable containers.

I do use raw arrays on occasion, but they are certainly not my tool of first resort.

gblues said:
Code:
int function(int *arr[], int size)

This function accepts a pointer to a reference to an array (or, a pointer to a pointer to an element in an array), and an integer size parameter.
Actually, that's an array of int pointers.

The function that takes a pointer to an array looks like this:
Code:
int function(int (*arr)[], int size)

There are important differences between the two.
 
Slavik81 said:
Array notation doesn't guarantee a contiguous allocation of objects. Or even that there will be an object.

For example,
int array[1]; // Only one element

or even,
function(NULL, 0); // No compile error

Pointer notation and array notation are exact synonyms for each other. Following two lines are 100% equivalent:

Code:
void f(int* x);
void f(int x[]);

There is a slight chance that a language lawyer can point out a minor difference in the above lines, probably with regards to implicit conversion rules or casting, but I am pretty sure they are exactly the same.

By extension, following two lines are also equivalent:

Code:
void f(int** x);
void f(int* x[]);
 
Slavik81 said:
If you'd like to explain why you should use raw arrays whenever possible, use array notation when passing raw arrays into functions, or use 2D arrays instead of simple template classes that compile into nearly identical code, I'd love to hear it.

What kind of simple template class are you referring to? I hope not boost::multi_array.
 

Slavik81

Member
cpp_is_king said:
What kind of simple template class are you referring to? I hope not boost::multi_array.
Depends on what you want. For single-dimensional arrays there's c_array<T,N>. Statically allocated 2d arrays could be done similarly, with their second dimension also specified as template parameter.

Unfortunately, you can't create the syntax for [][] without jumping through hoops that boost does. But, you can just name the accessors something like 'at' or 'ij'. Or use operator() if you really like operator overloading.

For a dynamically allocated 2d array (the kind I most commonly encounter), maybe something like this:

Code:
template <class T>
class DynamicArray2d
{
public:
	DynamicArray2d(int rows, int columns);

	T& at(int row, int column);
	const T& at(int row, int column) const;

	int rows() const;
	int columns() const;

private:
	std::vector<T> data_;
	int rows_;
	int columns_;
};

template <class T>
inline DynamicArray2d<T>::DynamicArray2d(int rows, int columns)
	: data_(rows*columns)
	, rows_(rows)
	, columns_(columns)
{
}

template <class T>
inline T& DynamicArray2d<T>::at(int row, int column)
{
	return data_[row*columns_+column];
}

template <class T>
inline const T& DynamicArray2d<T>::at(int row, int column) const
{
	return data_[row*columns_+column];
}

template <class T>
inline int DynamicArray2d<T>::columns() const
{
	return columns_;
}

template <class T>
inline int DynamicArray2d<T>::rows() const
{
	return rows_;
}
 

rexor0717

Member
Hey GAF, I have a question. I have two doubles that are being divided. I store the result in a variable, doubleVar. I then try to print this double, but it just says 0. I do it like this:
cout<< doubleVar;

But all I get is a zero, even though the double definitely has a value besides zero. Whats going on? Is there some kind of special double properties that I don't know about.
 

CrankyJay

Banned
rexor0717 said:
Hey GAF, I have a question. I have two doubles that are being divided. I store the result in a variable, doubleVar. I then try to print this double, but it just says 0. I do it like this:
cout<< doubleVar;

But all I get is a zero, even though the double definitely has a value besides zero. Whats going on? Is there some kind of special double properties that I don't know about.

try printf("%d", doubleVar);

or %f ... I forget which.
 
Is there any reason you guys think this will actually work considering his code is a perfectly fine way of printing a double? Maybe we need to see more of his code
 

10011101001

Neo Member
rexor0717 said:
Hey GAF, I have a question. I have two doubles that are being divided. I store the result in a variable, doubleVar. I then try to print this double, but it just says 0. I do it like this:
cout<< doubleVar;

But all I get is a zero, even though the double definitely has a value besides zero. Whats going on? Is there some kind of special double properties that I don't know about.

If you are dividing double by double, this should work fine. Are you entering the values directly or are they results of earlier calculations? My guess is you are either getting a zero into your equations or you are doing integer division somewhere.
 

rexor0717

Member
Turned out I doing something like:
double var = 1/4;
instead of
double var = 1.0/4.0;

That solved the problem. I was just being dumb. I'm fairly new to C++. Thanks for the help though.
 

10011101001

Neo Member
rexor0717 said:
Turned out I doing something like:
double var = 1/4;
instead of
double var = 1.0/4.0;

That solved the problem. I was just being dumb. I'm fairly new to C++. Thanks for the help though.
You're welcome. If you don't know about it already, an easy way to avoid this is type cast. It is one of your best friends for computationally heavy programs. For example:
Code:
int var1 = 1;
int var2 = 4;
double var3 = (double)var1 / (double)var2;
This will convert the var1 and var2 into doubles for the calculation, so the answer will come out correctly.
 

Feep

Banned
10011101001 said:
You're welcome. If you don't know about it already, an easy way to avoid this is type cast. It is one of your best friends for computationally heavy programs. For example:
Code:
int var1 = 1;
int var2 = 4;
double var3 = (double)var1 / (double)var2;
This will convert the var1 and var2 into doubles for the calculation, so the answer will come out correctly.
You do not need to cast the second variable; a double divided by an integer still yields a double. Save some time!
 

Fafalada

Fafracer forever
poweld said:
but it's not as though arrays are evil.
The concern is what people do with them (most things condemned in programming aren't really evil by themselves, yet some are actually taught by schools as "evil" regardless).
 
Fafalada said:
The concern is what people do with them (most things condemned in programming aren't really evil by themselves, yet some are actually taught by schools as "evil" regardless).

Exactly. Lately I've found myself using more and more gotos. The difference between a good programmer and an average programmer is the good one knows when things are ok.

I still get in arguments with people over gotos sometimes, it's amazing what people will defend without ever having thought about the problem with their own brains and without attempting to have their own ideas on the matter.

That being said, if people are doing stupid things with arrays, then I have to say they are probably terrible programmers, because the concept really isn't that difficult.
 

Chichikov

Member
I'm not a dogmatic programmer, I'm really not.
But there are very few places where goto use is justified.

An over-reliance on them will make your code extremely inflexible.
 
Chichikov said:
I'm not a dogmatic programmer, I'm really not.
But there are very few places where goto use is justified.

An over-reliance on them will make your code extremely inflexible.

Ever used a switch statement?
 

10011101001

Neo Member
Sorry, I have to...
goto.png



cpp_is_king said:
Ever used a switch statement?
Even here I haven't seen a need for a goto...If you're talking about getting out of the switch, 'break' does just fine. Most other items I have found work fine in function calls and modifying code around my switches slightly.

I personally prefer to avoid gotos, primarily because they are a pain to maintain and also because they are kind of a dated concept. Like I said above, I can get most all the functionality out of functions and classes, and that way all my logic gets contained to modules for easier debugging and such.

Theres nothing wrong with gotos, but they can easily screw you over if you don't know what you are doing.
 
10011101001 said:
Sorry, I have to...
goto.png




Even here I haven't seen a need for a goto...If you're talking about getting out of the switch, 'break' does just fine. Most other items I have found work fine in function calls and modifying code around my switches slightly.

I personally prefer to avoid gotos, primarily because they are a pain to maintain and also because they are kind of a dated concept. Like I said above, I can get most all the functionality out of functions and classes, and that way all my logic gets contained to modules for easier debugging and such.

Theres nothing wrong with gotos, but they can easily screw you over if you don't know what you are doing.

Lol at the picture. I was so tempted to use goto last week to solve the n-queens problem in parallel. Then my lab partner called me crazy and we proceeded to take a different approach.
 
10011101001 said:
Sorry, I have to...
goto.png




Even here I haven't seen a need for a goto...If you're talking about getting out of the switch, 'break' does just fine. Most other items I have found work fine in function calls and modifying code around my switches slightly.

I personally prefer to avoid gotos, primarily because they are a pain to maintain and also because they are kind of a dated concept. Like I said above, I can get most all the functionality out of functions and classes, and that way all my logic gets contained to modules for easier debugging and such.

Theres nothing wrong with gotos, but they can easily screw you over if you don't know what you are doing.

I'm talking about the "case" label. It actually is a goto. Ever tried to declare a variable inside a case statement in C / C++ and gotten a compiler warning "initialization of variable x skipped by case label"? That's because the case is quite literally a goto in every sense of the word. It has the exact same semantics. It even lets you write code that doesn't look like it would be compileable:

Code:
        switch(n){
        case 0:
                do{      
                        *to = *from++;
        case 7:               
                        *to = *from++;
        case 6:               
                        *to = *from++;
        case 5:               
                        *to = *from++;
        case 4:               
                        *to = *from++;
        case 3:               
                        *to = *from++;
        case 2:               
                        *to = *from++;
        case 1:               
                        *to = *from++;
                }while(--n>0);
        }
}
Each case is literally a goto.

Same thing with exceptions, except these little fuckers can goto anywhere in your entire program. It's like an inverse goto. Instead of "goto the place I want you to go to", it's "goto the place that wants you to go to it". Yea good luck with reasoning about your flow of execution there.

BTW, that's one of my favorite xkcd's
 

10011101001

Neo Member
Oh alright, we're talking past each other apparently. I'm mostly concerned with direct use of "goto", since the structure is solely maintained by the programmer. Since cases are contained into the switch statement, and exception handling to try catch blocks, there is a bit of automatic control to where the goto part of the statement actually points to.

I've used switches and exceptions plenty in my code, so if you look at it from your perspective, I use goto functionality quite a bit.
 

Chichikov

Member
cpp_is_king said:
I'm talking about the "case" label. It actually is a goto. Ever tried to declare a variable inside a case statement in C / C++ and gotten a compiler warning "initialization of variable x skipped by case label"? That's because the case is quite literally a goto in every sense of the word. It has the exact same semantics. It even lets you write code that doesn't look like it would be compileable:
[snip]
Each case is literally a goto.

Same thing with exceptions, except these little fuckers can goto anywhere in your entire program. It's like an inverse goto. Instead of "goto the place I want you to go to", it's "goto the place that wants you to go to it". Yea good luck with reasoning about your flow of execution there.

BTW, that's one of my favorite xkcd's

A switch statement is a very useful control mechanism when used as intended.
And while I don't think it's too far fetched to think of it as a constrained goto, it's exactly this constrain that makes it useful and safe, if used properly.
Now it's true, you can use a switch statement to do horrible goto-esque things, but this is c++ we're talking about, you can commit crimes against computer science with a for loop.

And you're wrong about exceptions.
Though it's probably worth mentioning that I was never a fan of the c++ structured error handling mechanism.
I actually think it's more trouble than it's worth.
 

maharg

idspispopd
All control structures are built on goto (or rather jmp). Every. Single. One. Of. Them. So saying "lol good luck not using gotos when you use switches!" is disingenuous, since you could say the same about while, for, do, calling a function, or return. Duff's device (seen above) is a clever little hyper-optimization, but if you use it and you don't need it you're a dick. If you use it and you don't document the hell out of it you're an asshole. And very few people ever work on anything that really needs it.

Most of the real harm goto can do is fairly restricted from actually happening, since you can't directly do a long jump. Gotos have only one solid use in C as far as I'm concerned, though: Complex resource cleanup scenarios. In C++ even that use case is pretty much eliminated through the use of RAII.

Something being useful is not the same as it being usable as a standard tool. A jackhammer is a useful tool, but you're not going to see one in every handyman's garage.
 
Chichikov said:
And you're wrong about exceptions.
Though it's probably worth mentioning that I was never a fan of the c++ structured error handling mechanism.
I actually think it's more trouble than it's worth.

How am I wrong about exceptions? I'm not saying that you're wrong, I just don't know specifically what part you think I'm wrong about
 
Status
Not open for further replies.
Top Bottom