Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


brosmike posted:

The most likely cause is that you're not including the function template definition in your World source file. Since function templates are not instantiated for particular template types until they're actually used, you can't just include declarations in a header file and leave the implementation for the linker to deal with. The implementation for the particular T you use literally does not exist for the linker to find unless the compiler creates it for you, which it doesn't know how to do if you haven't included the template definition.

TLDR: Put definitions of function and class templates in header files.

This was it, thanks. That's not something I knew about templates, but I'll be sure to remember it in the future.

EDIT:

Plorkyeran posted:

This code is nonsensical and shouldn't even compile. There's no reason to copy the passed object into a temporary buffer, and this isn't even a valid way of doing that.

Huh, it compiles fine. I'm basing this off of an old tutorial I found way back, and keep coming back to for file IO stuff. It says that the first argument for write() is const char* - are you suggesting just doing something along the lines of:
code:
_Stream.write( &T , sizeof( T ) );
or
code:
_Stream.write( &(char)T , sizeof( T ) );
?

Adbot
ADBOT LOVES YOU

nielsm
Jun 1, 2009



Staggy posted:

code:
_Stream.write( &T , sizeof( T ) );

This looks fine. sorry no, see below

Also, you may want to make the argument to your Write function a const reference, rather than a simple value type. Using a simple value type causes additional copies at runtime and if you have copy constructors defined for the types, those will also be called, along with any destructor.


E: vvv You're completely right, it should be _Stream.write(&data, sizeof(T));

nielsm fucked around with this message at 22:11 on May 23, 2011

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe
^^^^^
really, am I missing something here?

It should be:

code:
_Stream.write(&data, sizeof(T))
Because T refers to a data type, not an actual class instance/variable. Otherwise if you had this:

code:
BinaryFile<MyClass>
Then your code ends up as:

code:
_Stream.write(&MyClass, sizeof(MyClass))
which is invalid code.

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Gerblyn posted:

code:
_Stream.write(&data, sizeof(T))
Because T refers to a data type, not an actual class instance/variable. Otherwise if you had this:

Yeah, meant to put &data the firs time. This is something I do constantly when I'm using templates.

And that's great, if I can just do that. Cheers.

EDIT: That doesn't work, I'm just getting "Cannot convert parameter 1 from..." errors.

Staggy fucked around with this message at 22:19 on May 23, 2011

nielsm
Jun 1, 2009



Staggy posted:

EDIT: That doesn't work, I'm just getting "Cannot convert parameter 1 from..." errors.

Grats, you managed to skip the really interesting part of the error message making it completely useless for diagnostics.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Staggy posted:

EDIT: That doesn't work, I'm just getting "Cannot convert parameter 1 from..." errors.
code:
Stream.write((char*)&data, sizeof(T))
Edit: In fact, why not go with
code:
Stream.write((char*)&data, sizeof(data))
(Assuming data is an instance of T, I haven't looked back to check.)

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


nielsm posted:

Grats, you managed to skip the really interesting part of the error message making it completely useless for diagnostics.

My bad. It was variations on "..from int to const char*" depending on what I was trying. Not sure why I stopped typing there.

roomforthetuna posted:

code:
Stream.write((char*)&data, sizeof(T))
Edit: In fact, why not go with
code:
Stream.write((char*)&data, sizeof(data))
(Assuming data is an instance of T, I haven't looked back to check.)

data is an instance of T, yes. And that works, thanks - I swear I tried that, plus several variations of it, with no luck. I think my brain is on the fritz.

Templates make me feel like I'm trying to get to grips with pointers all over again. I don't know how, but I just did not get pointers to start with.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Staggy posted:

Templates make me feel like I'm trying to get to grips with pointers all over again. I don't know how, but I just did not get pointers to start with.
It might help if you realize that templates are more akin to #define than anything else - they don't do anything on their own, and then when you reference the template it writes out the code with your <whatever> in place of the parameters. Obviously it's a bit cleverer than that, it doesn't just dump the generated code out in the middle of whatever function you're in at the time like a #define macro would, but the behavior is like #define in that you need the whole function to exist in the header and it approximately works by simply substituting whatever parameters you gave it every time the parameter occurs inside the 'macro', just like a #defined macro would.

aux
Oct 25, 2010

Staggy posted:

Templates make me feel like I'm trying to get to grips with pointers all over again. I don't know how, but I just did not get pointers to start with.

Have you worked with STL templates? they are great for understanding templates

If you come from a java background though, template would be kind of hard to understand.
They are the same in principle, instead of object references in Java, in C++ you supply the object type as a parameter when you create the template object

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Staggy posted:

Templates make me feel like I'm trying to get to grips with pointers all over again. I don't know how, but I just did not get pointers to start with.
Think of them a bit like the mad libs you probably did as a kid where you had to pop in a noun or an adverb or something to complete a story. Writing a template is like writing out the mad lib with the slots, and implementing it is giving it things to use there. The most common thing to pop into a template would be a data type; a lot of containers are written to handle that to be flexible. Beyond that some will ask for code too. If you're trying to create something like a hash map using some kind of template in C++, you'll at some point probably have to pass along to it a predicate function and a comparison so the hash map knows what to do on collisions.

They wouldn't be so scary though if compilers didn't poo poo out pages on pages on pages of stuff if you botch up some part of it. The Boost Python wrappers particularly amuse me because you'll put in one line of templated stuff, and sometimes get back three pages of errors, with something in the middle of the garbage they hard-coded some stuff so that in the error you get "you_screwed_up_dumbass_you_should_have_used_the_const_version."

Edit: drat--forgot to post about what I had wanted originally. I got into a floating-point precision kind of thing the other day. To reproduce the bug I was hoping to assign doubles to the hex representation of a floating point number. I wondered if there was a convenience function in the standard libraries or boost for this. But failing that, I suppose I can use a union to create the hex value as an unsigned long going into a double. I am wondering about printing this stuff out though. Within Eclipse CDT while debugging it was showing what looked to be 2.5 as something like 2.500000xyz. The hex quantity looked very solid so I suspect it was rounding how it was printing it. Is there anything for showing it as it exactly is?

Rocko Bonaparte fucked around with this message at 00:08 on May 24, 2011

brosmike
Jun 26, 2009

aux posted:

If you come from a java background though, template would be kind of hard to understand.
They are the same in principle, instead of object references in Java, in C++ you supply the object type as a parameter when you create the template object

I have absolutely no idea what you're trying to say here, but you need to be careful - though Java Generics and C++ templates look similar and are often used for similar purposes, they are absolutely not "the same in principle".

Templates are pretty much glorified, slightly more type safe macros - your template definition basically tells the compiler how to generate code, and the compiler uses it to generate a new function/class every time you parameterize it by a new type. A MyList<Foo> and a MyList<Bar> are entirely different classes. This allows you to do things like implement special versions of your poo poo for special cases - say, if you want a common list interface for all types despite knowing a more efficient implementation trick if your list elements happen to be ints. It also means you can do many metaprogramming tricks with templates (calculating factorials at compile time is a common example, but isn't really super useful. The boost library makes rampant use of template metaprogramming, if you want more practical examples).

Generics are very different - they are purely a compile-time type safety mechanism. They exist ONLY so that the compiler can give you an error when you try to do something that isn't type safe - say, trying to shove a Bar object into a List<Foo>. At run time, it's just a List, not a List<Foo> as far as the Java virtual machine is concerned.

For simple parameterization, they act similarly - to a programmer not concerned about underlying implementation details, using templates with std::vector and generics with java.util.ArrayList look and behave similarly. But once you start implementing your own templates/generic classes, the differences can become important quickly. Can I construct a new T object? Can I print the real name of the T class? Do Ts have to be objects, as opposed to primitives?

aux
Oct 25, 2010

brosmike posted:

knowing a more efficient implementation trick if your list elements happen to be ints.

I dont know why anyone would ever do that, sounds like a coding horror to me.
If your argument is that C++ templates are different than C# generics because C++ allows metaprogramming, then its not really the case cause C# also allows some metaprogramming and code generation just like C++.

aux fucked around with this message at 02:11 on May 24, 2011

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

aux posted:

I dont know why anyone would ever do that, sounds like a coding horror to me
The standard templates do it for bools to keep them from taking up 32 times more space than they need.

vvvv Ha, that's true. But still, "to reduce required space by an order of magnitude" is an answer to why anyone would ever do that.

roomforthetuna fucked around with this message at 03:28 on May 24, 2011

brosmike
Jun 26, 2009

roomforthetuna posted:

The standard templates do it for bools to keep them from taking up 32 times more space than they need.

(and it is widely considered a coding horror :ssh:)

Aux posted:

If your argument is that C++ templates are different than C# generics because C++ allows metaprogramming, then its not really the case cause C# also allows some metaprogramming and code generation just like C++.

My argument was that C++ templates are different from Java generics (I have no idea how C# does it) because their implementations are very different, and that this happens to have a variety of implications on metaprogramming and code generation when using one or the other.

brosmike fucked around with this message at 02:40 on May 24, 2011

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

brosmike posted:

(I have no idea how C# does it)

C# is a mix of both, really. It emits a different implementation every time you instantiate it with a value type, but uses a single implementation for all reference types you use it with.

chiyosdad
May 5, 2004

"I wish I were a bird!"
I have a weird bug that I'm not sure how to debug, because the value of my variable changes when I try to measure it (like some sort of quantum bug)...

I have my own templated Matrix<T> class. My program does something like this:

code:
// do some computation to obtain A
// I know what the answer should be, so initialize A_exact with the actual answer

cout << error(A, A_exact) << endl;
(error(A,A_exact) basically computes the maximum of abs(A[i][j] - A_exact[i][j]). [] is an operator that returns a self-implemented vector class which has its own [] operator, and so A[i][j] returns the i,jth entry of A, which is a double.)

The error was larger than it should be, so I wanted to see exactly what was going on, and appended the following code:

code:
for(int i = 0; i < A.Nx; i++)
	for(int j = 0; j < A.Ny; j++)
		if( abs( A[i][j] - A_exact[i][j] ) > .01)
			cout << i << '\t' << j << '\t' << A[i][j] << '\t' << A_exact[i][j] << endl;
When I ran it again, the output of the first cout changed! This is quizzical for two reasons; first, the code that I appended does not change the data in any way, so why should the value of error(A, A_exact) be different? Secondly, the code that I appended comes AFTER everything, so how could it retroactively affect a computation that was done before??? I am really baffled by this behaviour. Not only is it a quantum bug, it's also a bug that can travel back in time, apparently. The only thing to cause the two different outputs was the appended code snippet; nothing else was changed. Any ideas?

chiyosdad fucked around with this message at 06:31 on May 24, 2011

TasteMyHouse
Dec 21, 2006
can you post the rest of the code?

chiyosdad
May 5, 2004

"I wish I were a bird!"
The rest of the code is like 5000 lines long; it's a pretty involved computation...

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Did you try running the computation multiple times before you added that snippet?

Have you tried running it under a debugger and looking at the memory yourself rather than printing it out?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
You have a memory or uninitialized-variable bug, and changing frame layouts changes the symptoms.

Duke of Straylight
Oct 22, 2008

by Y Kant Ozma Post

roomforthetuna posted:

I've never really thought about that - where does the compiler/linker put the functions generated from a template?

If, for example, I have a template defined in header "mytemplate.h" and then I have mytemplate<int> used in both foo.cpp and bar.cpp, which of those object files does mytemplate<int> end up compiled into? Or both? Or some special separate place?

Depends on the compiler. And the compiler options. I tested this out really quickly and it seems Plorkyeran is correct that at least g++ compiles all of the instantiations by default and throws the extra copies away in linking, but it does also have an option to use a separate template repository.


Rocko Bonaparte posted:

drat--forgot to post about what I had wanted originally. I got into a floating-point precision kind of thing the other day. To reproduce the bug I was hoping to assign doubles to the hex representation of a floating point number. I wondered if there was a convenience function in the standard libraries or boost for this. But failing that, I suppose I can use a union to create the hex value as an unsigned long going into a double. I am wondering about printing this stuff out though. Within Eclipse CDT while debugging it was showing what looked to be 2.5 as something like 2.500000xyz. The hex quantity looked very solid so I suspect it was rounding how it was printing it. Is there anything for showing it as it exactly is?

reinterpret_cast?

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Thanks for the template explanations - I think it's getting a bit clearer.

One question I do have though - if explicit specialisations of a templated function have to go in a header file in order to be found and used, how can I avoid defining them multiple times?

BinaryFile.h has the definitions for the templated functions Read() and Write() in it.
BinarySave.h includes BinaryFile.h, and has explicit specialisations of Read() and Write() for std::string, and a few other data types.
When I want to use this, I include BinarySave.h - but trying to use this in more than once place leads to

quote:

1>World.obj : error LNK2005: "public: void __thiscall BinaryFile::Write<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$Write@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@BinaryFile@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in MainScene.obj
and so on.

I'm doing the
code:
#ifndef FILE_NAME
#define FILE_NAME

...

#endif
trick in each file, but this doesn't help.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
The ifndef dance doesn't help you here because this is a link-time error. You have two options: forward-declare full specializations and define them in a separate file as with normal functions, or label them inline.

wellwhoopdedooo
Nov 23, 2007

Pound Trooper!

Rocko Bonaparte posted:

Edit: drat--forgot to post about what I had wanted originally. I got into a floating-point precision kind of thing the other day. To reproduce the bug I was hoping to assign doubles to the hex representation of a floating point number. I wondered if there was a convenience function in the standard libraries or boost for this. But failing that, I suppose I can use a union to create the hex value as an unsigned long going into a double. I am wondering about printing this stuff out though. Within Eclipse CDT while debugging it was showing what looked to be 2.5 as something like 2.500000xyz. The hex quantity looked very solid so I suspect it was rounding how it was printing it. Is there anything for showing it as it exactly is?

code:
#include <iomanip>
#include <iostream>
#include <limits>

using namespace std;

int main () {

        double x = 0.1;

        cout << setprecision(numeric_limits<double>::digits10 + 20) << x << "\n";

        return 0;

}

$ ./butt
0.1000000000000000055511151231257827
Of course, if it was 2.5, your error is coming from somewhere else, as 2.5 can be exactly represented by a float. Just stuffing a double into a long won't work though, at best you'd either get nonsense or a truncated number, I'm not sure which anymore, but this frustrated me so badly that I wrote something to parse floats (mostly as a learning exercise, so please don't laugh too hard at anything you see here):

http://pastebin.com/3fGPaKyN

More edifying than that paste is http://en.wikipedia.org/wiki/Floating-point#Internal_representation, and:
code:
      struct _DoubleBits {
        unsigned int mantissal;
        unsigned int mantissah : 20;
        unsigned int exponent  : 11;
        unsigned int sign      :  1;
      };

      union _DoubleParts {
        double      number;
        _DoubleBits bits;
      };

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


Mustach posted:

The ifndef dance doesn't help you here because this is a link-time error. You have two options: forward-declare full specializations and define them in a separate file as with normal functions, or label them inline.

Excellent, thanks.

dos4gw
Nov 12, 2005
I know this is a really stupid question but I'm completely new to programming.

I want to learn C and I've got a copy of the Kernighan & Ritchie book but it only describes compiling in Unix. I'm using Windows 7 and I asked my friend, who said that I could install Cygwin and use GCC and a shell but I'd rather keep it as simple as possible to start with and avoid doing that.

He told me to get Visual Studio Express from the Microsoft site, which I've done, but having installed it, other than some SQL server stuff I can only see Visual Basic 2010 Express, which seems to be for Visual Basic and not C. The links in the OP were all for C++ related things so I don't really know what the hell I'm doing to be honest.

Am I in fact meant to be using Visual Basic to compile? I was writing code in Notepad++ to start with but obviously this isn't going to get anything compiled. My problem is that when I try to start a new project I have to choose between things like 'Console Application' and 'Windows Forms Application' which seems overly complicated because all I want to do is write a simple Hello World program.

That Turkey Story
Mar 30, 2003

seagullofdeath posted:

Am I in fact meant to be using Visual Basic to compile? I was writing code in Notepad++ to start with but obviously this isn't going to get anything compiled. My problem is that when I try to start a new project I have to choose between things like 'Console Application' and 'Windows Forms Application' which seems overly complicated because all I want to do is write a simple Hello World program.

You want "Visual C++ 2010 Express", not Visual Basic. When you have Visual C++ installed, you want to either start with "Empty Project" or "Console Application".

http://www.microsoft.com/express/Downloads/#2010-Visual-CPP

nielsm
Jun 1, 2009



As far as I know, there is no one product called "Visual Studio Express". You get one of the languages in Express edition at a time, so you've most likely downloaded Visual Basic Express, when you should have gotten Visual C++ Express.

e:fb

dos4gw
Nov 12, 2005
Thanks, I downloaded the right one this time!

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Keep in mind that you can still compile from the command line. There's a shortcut under the VC++ Express start menu folder that sets up the environment for you. The compiler/linker's name is cl.

Captain Snaps
Jul 27, 2003

Maintol!
I have a problem that I am having a hard time wrapping my head around. I am trying to create a class to store color data for a tetris clone that I am writing as an exercise. The problem seems to be when I write the header file for said class. When I go to write the implementation file to initialize the three float variables in the class, Visual studio gives me Error:Incomplete type is not allowed. I have the header file properly included in the implementation file.

After wrestling with this problem for a while, I just copied and pasted another header file from another class, and just edited it to suit my needs. THAT works ok, but I can't figure out what the difference in the two class declarations are.

code:
#ifndef COLOR_H
#define COLOR_H

/*
class Color (
	float cRed, cGreen, cBlue;
public:
	Color(float, float, float);
);
*/

class Color {
    float cRed, cGreen, cBlue;
public:
    Color(float, float, float);
};
#endif
I see no functional difference between the two, but switching out the comments between the two different declarations breaks the implementation, with the bottom one being the one that works. Someone please tell me where I am loving up, as I am having the same problem on another object.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
One is using parentheses rather than curly-braces. Apparently it's MSVC is detecting the return type being incomplete before it talks about the curly-braces.

Captain Snaps
Jul 27, 2003

Maintol!

rjmccall posted:

One is using parentheses rather than curly-braces. Apparently it's MSVC is detecting the return type being incomplete before it talks about the curly-braces.

:doh: I can hardly see the difference between the two. That's what I get for using a DLP TV as a monitor. Thanks.

HFX
Nov 29, 2004

Captain Snaps posted:

:doh: I can hardly see the difference between the two. That's what I get for using a DLP TV as a monitor. Thanks.

People give me grief for using Courier New, but ( and { are a lot more noticeable different then with other fonts.

qntm
Jun 17, 2009
I am just learning to use C and I cannot figure out how to have an array of arrays at all. In the example below, b is an array of pointers to other arrays. Since b contains pointers, the other arrays may be of various sizes. How do I find out the number of elements in one of the nested arrays?

code:
void main(int argc, char * argv[]) {
	int a0[] = {75, 67, 333, 5, 0}; // 5 elements
	int a1[] = {-4, 23324, 100009}; // 3 elements
	int *b[] = {a0, a1};

	printf("%d\n", a0);            // e.g. 1638220
	printf("%d\n", b[0]);          // e.g. 1638220, same as above

	printf("%d\n", *(a0));         // 75
	printf("%d\n", *(b[0]));       // 75

	printf("%d\n", sizeof(a0));    // 20 (i.e. 5 * sizeof(int))
	printf("%d\n", sizeof(b[0]));  // 4  (i.e. sizeof(int *))

	return;
}
I understand why sizeof is behaving the way it is, because each element of b is a pointer-to-int, but I don't know how to get the answer I want, which is 20, out of b.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
There is no way, you must keep track of the lengths yourself, or use a multi-dimensional array of fixed dimensions.

qntm
Jun 17, 2009
Well as is typical it seems that I have answered my own question as soon as I asked it. It seems that sizeof is a compile-time operator - something I have honestly never heard of until now, even after learning about #define and #ifdef.

code:
void callme(int array[]) {
	printf("%d\n", sizeof(array));
	return;
}

void main(int argc, char * argv[]) {
	int a[] = {1, 2, 3};
	int b[] = {1, 2, 3, 4, 5};
	callme(a); // "4"
	callme(b); // "4"
	return;
}
Honestly, I set out with the best of intentions. I knew before I started out, "C doesn't check array bounds and lets you access data from random locations in memory", so I decided I would always check array bounds myself. Nope!

TasteMyHouse
Dec 21, 2006
e: well, you figured it out on your own :)

qntm
Jun 17, 2009
Ah, so that's why you get told the number of arguments in argc as well as the arguments themselves in argv -- because otherwise there's literally no other way of finding out.

Outstanding.

E: Doesn't all of this lead to some fairly serious security bugs?

Adbot
ADBOT LOVES YOU

Brecht
Nov 7, 2009

qntm posted:

E: Doesn't all of this lead to some fairly serious security bugs?
Yes.

Beginner C people always start with arrays and arrays-of-arrays and passing arrays as parameters and blah blah, and I never understand why, because it's easily both the most confusing part of the language and the least practical. I can't think of the last time I defined an array in C outside of test driver code. Don't use arrays if you can avoid it.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply