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
Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

pseudorandom name posted:

Maybe you should compile it and see what happens instead of posting about it on the internet?

Fine. It turned out I was having unrelated problems with an initialization but gcc was deciding that pointing around that literal was the best way to tell me.

Adbot
ADBOT LOVES YOU

xPanda
Feb 6, 2003

Was that me or the door?

Mustach posted:

Don't define the template class/functions in a cpp file, put it in SequenceProperty.h.

Hmm. Trying this leads to forward declaration errors and 'invalid use of incomplete type 'struct Chain'' errors because it's trying to access the length() member. When I actually include the Chain.h header and remove the forward declaration, then the class isn't even recognised as a valid type at all! When I copy the .cpp file contents (except the #include SequenceProperty.h line) and paste it after the template class definition, I still get forward declaration errors. This is pretty confusing.

The Chain class is part of an inheritance tree of related classes, all of which seem to have forward declarations of each other. Is it possible that the order in which they are compiled may have some effect here?

Coffee Mugshot
Jun 26, 2010

by Lowtax

xPanda posted:

Hmm. Trying this leads to forward declaration errors and 'invalid use of incomplete type 'struct Chain'' errors because it's trying to access the length() member. When I actually include the Chain.h header and remove the forward declaration, then the class isn't even recognised as a valid type at all! When I copy the .cpp file contents (except the #include SequenceProperty.h line) and paste it after the template class definition, I still get forward declaration errors. This is pretty confusing.

The Chain class is part of an inheritance tree of related classes, all of which seem to have forward declarations of each other. Is it possible that the order in which they are compiled may have some effect here?

Can you post the new code you have? I thought I saw some typos in your other posted code, but you might have fixed them by now.

Johann Gambolputty
Jul 6, 2006
Couple of questions. New to C++ so I am trying to be careful with a lot of things.

Does anyone use Intel Math Kernal Library for Blas and Lapack operations? I think I implemented everything right, but I have some questions if anyone uses it.

As for simpler things. I am using Visual Studio 2010 and the debugger can only show the 1st value of a dynamic array. I googled around and the reasoning is the pointer only points to the first part of the array and how does the debugger know its size. My question is if the debugger doesn't know the size, then how does the program know not to use the other addressed memory for the array.

Also, how should I pass dynamic arrays in functions. I have a function that will create a dynamically sized array from an input file. And, then I want to use that array as a constructor argument.

code:
 
ClassA.h File Snippet--------------------
class ClassA
{
public:
	ClassA(int fooIn, double* foo2In);
private:
	int foo;
	double* foo2;
	
};

ClassA.cpp File Snippet------------------


ClassA::ClassA(int fooIn, double* foo2In)
{
	foo = fooIn;
	
	foo2 = foo2In;
	
}


Is this correct. Is there a better way? It compiles and gives me the variables. So everything looks ok. Just that whole debugger things worries me into thinking that I might inadvertently make foo2 into a single valued double or something. And that part of memory can be changed by the program later down the line without me knowing or something. Also, is it ok to delete the foo2In variable after I construct the object?

Johann Gambolputty fucked around with this message at 05:53 on Jun 28, 2010

shrughes
Oct 11, 2008

(call/cc call/cc)

Johann Gambolputty posted:

Also, how should I pass dynamic arrays in functions.

You should use vectors and pass them.

Johann Gambolputty posted:

And, then I want to use that array as a constructor argument.

Stop wanting that :)

Johann Gambolputty posted:

Is this correct. Is there a better way?

It depends on how much knowledge you want to have. First, you don't want to manually manage the size of an array along with the array, because why would you want to do that? So it makes sense just to use a vector (a resizable array) for this sort of thing. Then, you can deep-copy the vector. Or, if the caller is willing to give up ownership of the data, you can .swap the vectors, as commented out below, which means that the vector passed by reference will be emptied and foo2 will be filled with its data (in O(1) time because it just swaps pointers and length information around).

Or you could share the data by having foo2 be a vector<double>* -- this way you don't have to manually keep track of the length of the array, but you still have the risk of incorrectly keeping track of object lifetimes.

Or you could use a boost::shared_ptr< vector<double> > which will keep a reference count. (Or tr1::shared_ptr? I forget.)

(C++0x spoilers) Or you could have the API take advantage of move semantics? I don't know much about that.



code:
 
ClassA.h File Snippet--------------------
class Node
{
public:
	Node(vector<double>& foo2In);
private:
	vector<double> foo2;	
};

ClassA.cpp File Snippet------------------


ClassA::ClassA(vector<double>& foo2In)
{
	// foo2.swap(foo2In);

        // this below deep-copies the vector
	foo2 = foo2in;




	// coord = coordIn; // wtf is this :)
	
}
So, the choices you make depend on how safe and flexible you want to be while managing object lifetimes. There's a certain trade-off between safety, convenience, and efficiency here. Passing a pointer would be unsafe. Deep-copying the caller's vector<double> is safe and convenient, but inefficient. Using .swap(..) to avoid the deep-copy would be unsafe (since the caller has to know about this side-effect) and would be inconvenient if the caller wanted to keep a personal copy. Using a shared_ptr is occasionally inefficient, and it would be unsafe if you wanted to modify the vector later (and the caller didn't expect this), so it depends how you use the vector later. Such is the nature of C++.


Edit:

quote:

Also, is it ok to delete the foo2In variable after I construct the object?

I would suggest avoiding raw pointers entirely (avoid having to use "*" anywhere in a type you declare) until you understand the answer to this question.

shrughes fucked around with this message at 05:48 on Jun 28, 2010

Johann Gambolputty
Jul 6, 2006
I wouldn't mind using vectors. I just don't know if Intel MKL utilizes them for their BLAS/LAPACK routines. Also, I can't really have too huge of inefficiencies. I will be solving rather large matrices sometimes non-linearly so multiple iterations will be used. I would prefer something that is reasonably fast when passing my variables around. I will try to delve deeper into everything you suggested though.

And as for my delete question it leaves a dangling pointer. I figured as much just wanted to make sure.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Johann Gambolputty posted:

My question is if the debugger doesn't know the size, then how does the program know not to use the other addressed memory for the array.
It doesn't.

shrughes
Oct 11, 2008

(call/cc call/cc)

Johann Gambolputty posted:

I wouldn't mind using vectors. I just don't know if Intel MKL utilizes them for their BLAS/LAPACK routines. Also, I can't really have too huge of inefficiencies. I will be solving rather large matrices sometimes non-linearly so multiple iterations will be used. I would prefer something that is reasonably fast when passing my variables around. I will try to delve deeper into everything you suggested though.

Vectors are implemented internally with a contiguous array, so you should be able to pass &vec[0] and vec.size() wherever MKL expects a double* (or std::complex<double>* or whatever) array and its corresponding size. They're a useful tool in place of arrays, and if you find them useful, good.

Johann Gambolputty
Jul 6, 2006

Plorkyeran posted:

It doesn't.

Just trying to get a deeper understanding of things.

How does the delete operator work if the program can't find out at all how much memory/size the dynamic array is taking up?



shrughes posted:

Vectors are implemented internally with a contiguous array, so you should be able to pass &vec[0] and vec.size() wherever MKL expects a double* (or std::complex<double>* or whatever) array and its corresponding size. They're a useful tool in place of arrays, and if you find them useful, good.

Thanks that most likely will work.

shrughes
Oct 11, 2008

(call/cc call/cc)

Johann Gambolputty posted:

How does the delete operator work if the program can't find out at all how much memory/size the dynamic array is taking up?

Magic.

For primitive types, where the destructor doesn't actually have to do anything, there's no reason the delete operator would need to be able to figure out the size of the array. And so that value might not be stored in any standard location. In general, from the debugger's point of view, your pointer could be pointing to the middle of an array, or to a single element, or to a fixed-size array in a struct or on a stack. It would be :effort: for the debugger to recognize the case where your pointer is pointing to to the beginning of a region allocated on the heap, and even then it wouldn't know how large the intended region was, since the expression new double[113] could allocate an array of size 300 if it drat well pleases (since double is a primitive type and destructors don't do anything. For some arbitrary type where the destructor might print out a congratulatory message on stdout, its behavior would have to be distinguishable somehow.

shrughes
Oct 11, 2008

(call/cc call/cc)

shrughes posted:

For primitive types, where the destructor doesn't actually have to do anything, there's no reason the delete operator would need to be able to figure out the size of the array.

And for other types, the value is stored. Somewhere. For example:

code:
#include <string>
#include <iostream>
#include <stdint.h>

int main() {
  std::string* ss = new std::string[15];
  double* dd = new double[15];

  for (int i = 0; i < 15; ++i) {
    ss[i] += 'a' + i;
    dd[i] = (double)i*i;
  }
  

  uint64_t* p = (uint64_t*) ss;

  std::cout << "p = " << p << std::endl;
  for (int i = -10; i < 20; ++i) {
    std::cout << "p[" << i << "]: " << p[i] << std::endl;
  }

  p = (uint64_t*) dd;

  std::cout << "p = " << p << std::endl;
  for (int i = -10; i < 20; ++i) {
    std::cout << "p[" << i << "]: " << p[i] << std::endl;
  }

}
(Apparently my computer's a 64-bit computer. I didn't know.)

And here's the output I get, annotated with comments

code:
p = 0x100100088
p[-10]: 1297437784     // (0)
p[-9]: 429496729600
p[-8]: 0
p[-7]: 0
p[-6]: 0
p[-5]: 0
p[-4]: 0
p[-3]: 0
p[-2]: 0
p[-1]: 15               // (1)
p[0]: 4296016280
p[1]: 4296016312
p[2]: 4296016344
p[3]: 4296016376
p[4]: 4296016408
p[5]: 4296016440
p[6]: 4296016472
p[7]: 4296016504
p[8]: 4296016536
p[9]: 4296016568
p[10]: 4296016600
p[11]: 4296016632
p[12]: 4296016664
p[13]: 4296016696
p[14]: 4296016728
p[15]: 0
p[16]: 4607182418800017408
p[17]: 4616189618054758400
p[18]: 4621256167635550208
p[19]: 4625196817309499392
p = 0x100100100
p[-10]: 4296016440
p[-9]: 4296016472
p[-8]: 4296016504
p[-7]: 4296016536
p[-6]: 4296016568
p[-5]: 4296016600
p[-4]: 4296016632
p[-3]: 4296016664
p[-2]: 4296016696
p[-1]: 4296016728                 // (2)
p[0]: 0                                  // (3)
p[1]: 4607182418800017408
p[2]: 4616189618054758400
p[3]: 4621256167635550208
p[4]: 4625196817309499392
p[5]: 4627730092099895296
p[6]: 4630263366890291200
p[7]: 4632092954238910464
p[8]: 4634204016564240384
p[9]: 4635400285215260672
p[10]: 4636737291354636288
p[11]: 4638215034982367232
p[12]: 4639270566145032192
p[13]: 4640150175447252992
p[14]: 4641100153493651456
p[15]: 0         // (4)
p[16]: 1
p[17]: 1
p[18]: 0
p[19]: 97
(0) There are some uninteresting values before the array.

(1) For std::string, the new[] operator will apparently write the size right in front of the array (on my computer).

(2) For double, apparently it doesn't. And the array got allocated right next to the std::string array, with nothing in between!

(3) This is the first element of the double array, the double 0.0 is all zero bits. The others look like gobbleygook, of course, unless we displayed them in hexadecimal, in which case we'd see that most of their mantissa consists of zeros.

(4) Some uninteresting values after this array.

OddObserver
Apr 3, 2009
What OS are you running, shrughes? Is it a BSD by any chance?

shrughes
Oct 11, 2008

(call/cc call/cc)

OddObserver posted:

What OS are you running, shrughes? Is it a BSD by any chance?

Mac OS X Snow Leopard

I'm pretty sure something happened with the most recent version of Xcode or gcc or something :smith: because ghc has stopped working.

xPanda
Feb 6, 2003

Was that me or the door?

Rainbow Pony Deluxe posted:

Can you post the new code you have? I thought I saw some typos in your other posted code, but you might have fixed them by now.

Sure.

SequenceProperty.h
code:
#ifndef __SEQUENCE_PROPERTY_H
#define __SEQUENCE_PROPERTY_H

#include <algorithm>
#include <cstdio>
#include "containers/multi_array.h"
//#include "protein/Chain.h" // this makes no difference

class Chain; // forward declaration error

template<class Property>
class SequenceProperty
{
//private:
	Chain* _chain;
	unsigned int _seqLength;

public:
	SequenceProperty()
		: _chain(NULL), _seqLength(-1), _property_list()
	{
	}

	virtual void init(Chain* c); // tried defining here instead, same error

        /* more code... */

private:

	// the property array
	multi_array<Property> _property_list;

};

#include "protein/Chain.h" // this makes no difference

// move template from cpp file to header
template <class Property>
void SequenceProperty<Property>::init(Chain* c)
{
	// reallocate memory
	_seqLength = c->length(); // invalid use of incomplete type 'struct Chain', was expecting the #include to fix this
	// put in an extra one at the end to
	// simplify some range checking
	_property_list.resize(_seqLength+1);

	_chain = c;
}

#endif
Having both of the #include "protein/Chain.h" commented out doesn't make a difference so long as the forward declaration of Chain is still in there, but commenting out the forward declaration leads to Chain being an unknown type. This doesn't change with commenting or un-commenting one/both of the #include "protein/Chain.h" lines, which I don't get. Why wouldn't it know the Chain type when I include it?

The Chain class is pretty ordinary I think, it's a non-template class:
code:
class Chain
	: public Entity<Residue, Structure>
{
        ...
}
Oh and here's the compiler output for good measure:
code:
protein/SequenceProperty.h: In member function ‘virtual void SequenceProperty<Property>::init(Chain*)’:
protein/SequenceProperty.h:82: error: invalid use of incomplete type ‘struct Chain’
protein/SequenceProperty.h:11: error: forward declaration of ‘struct Chain’
In file included from protein/Residue.h:10,
                 from protein/Chain.h:7,
                 from ../protein/Structure.h:7,
                 from ../Backbone.h:7,
                 from ../Backbone.cpp:1:
It looks like the include path has already gone through Chain.h before it gets to SequenceProperty.h, which might explain the forward declaration error and why the include lines do nothing, but doesn't explain why Chain is not a recognised type. Or do I have it backwards? Interesting and frustrating.

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.

Plorkyeran posted:

It doesn't.

I think you're misinterpreting Johann Gambolputty's question. I think what he's asking is how new doesn't return an address that overlaps with an already-allocated chunk of memory and how delete knows "how much" to delete. The answer to that question is that the underlying memory allocator keeps track of all of this in a hidden internal data structure.

The debugger doesn't know about this because it can't: pointers can point to a single element or multiple elements, and there's no way to tell. Debuggers can't look at the memory allocator's data structures because while memory allocation is usually handled by the standard runtime library, you can swap out the standard implementation for a custom one if you really want to (Firefox does this, for example, to help combat memory "leaks").

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
It doesn't say it's an unrecognized type, it says it's an incomplete type, which means it's been declared but not yet defined. And yes, this is because your headers have a cyclic depdendency.

If Chain.h absolutely requires SequenceProperty.h (or rather, absolutely requires Residue.h which absolutely requires SequenceProperty.h), you might have to abandon the one-class-per-header rule you've apparently been working with, or at least do some funky restructuring (e.g. putting out-of-line method definitions in "more derived" headers).

Johann Gambolputty
Jul 6, 2006

Mr.Radar posted:

I think you're misinterpreting Johann Gambolputty's question. I think what he's asking is how new doesn't return an address that overlaps with an already-allocated chunk of memory and how delete knows "how much" to delete. The answer to that question is that the underlying memory allocator keeps track of all of this in a hidden internal data structure.

The debugger doesn't know about this because it can't: pointers can point to a single element or multiple elements, and there's no way to tell. Debuggers can't look at the memory allocator's data structures because while memory allocation is usually handled by the standard runtime library, you can swap out the standard implementation for a custom one if you really want to (Firefox does this, for example, to help combat memory "leaks").

Thanks Mr. Radar precisely what I was asking. I find all this really interesting.

OddObserver
Apr 3, 2009

shrughes posted:

Mac OS X Snow Leopard


I see. Looking at it, its memory allocator doesn't store heap information for sufficiently small allocations inline. Neither does FreeBSD's phkmalloc, which has a pretty unorthodox design.

Linux/glibc use a very classical design --- it's a derivate of dlmalloc, which is basically an ultra-well engineered version of the algorithms one would find described in TAOCP... So on a 32-bit machine, altering the code in the obvious way, for the string array you'll find something like:


p[-2]: 0x49
p[-1]: 0xf
p[0]: 0x804a884
p[1]: 0x804a89c
p[2]: 0x804a8b4
....

Here, it conceptually allocates (15+1)*4 = 64 bytes for the array plus the non-POD operator[]'s size storage[1]. The 0x49 is 72 + 1, with the 1 being a a bitfield denoting that previous block isn't free, with 72 being some sort of internal size. The difference between 64 and 72 is for 4 bytes of overhead, +4 bytes for... bah, it's too late and I am too tired to figure it out. Anyway, the most important property of such allocators when it comes to this discussion is that:

1) If you have a pointer to the beginning of the block, you can figure out the size easily... But for a non-POD, the pointer won't be to the beginning of the block if new[] was used, due to the hidden size field --- and whether that's the case or not, that can't be determined from just the type.

2) If you have a pointer somewhere in the heap, it is actually possible to determine the size of the block --- but you pretty much have to walk the entire drat heap to figure it out, though there may be some shortcuts based on page management and the like. Fancier designs might actually be able to do it easier, depending on the kind of data structures they use.

[1] Interestingly the size is stored in the caller code directly -- both the POD and non-POD versions call _Znaj; and delete[] on a non-POD actually emits an entire loop.

beuges
Jul 4, 2005
fluffy bunny butterfly broomstick

Johann Gambolputty posted:

As for simpler things. I am using Visual Studio 2010 and the debugger can only show the 1st value of a dynamic array. I googled around and the reasoning is the pointer only points to the first part of the array and how does the debugger know its size.

The rest of your original post has been responded to pretty thoroughly, but just fyi, if you want to examine the contents of a dynamically allocated array in VS, add the pointer to the watch window, and add a comma followed by the number of elements you want to look at. E.g. if your pointer is called ptr, and you want to treat it as a 10-element array, then add a watch item called 'ptr,10'. The watch window will then show you 10 elements of your array. If ptr actually only points to an array of 5 elements, then the watch window will still show you 10 elements, but the last 5 will be random stuff in the memory immediately after your 5-element array. You can also perform casts and so-on in your watch window entries as well.

Lexical Unit
Sep 16, 2003

I've got an ambiguous overload error that I'd like to figure out how to work around. Here's the sample code: http://codepad.org/vHjbW01E

s = f; fails because the compiler doesn't know if I want:

string& string::operator=(const string&)
     or
string& string::operator=(const _CharT*)
     or
string& string::operator=(_CharT)

What I want is to force selection of string& string::operator=(const string&). But I really don't see any way to do this.

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.

Lexical Unit posted:

But I really don't see any way to do this.
Yep, so don't do it.

Lexical Unit
Sep 16, 2003

But I really want to :qq:

clearly not a horse
May 8, 2009

undue butt brutality is not a criminal offense
I am exploring the STL, looking for a container type like a set, but sequenced, so that I can access elements of its members by it's position. More like an array of pointers, but I should not be able to have two of the same sort. Which one? Or is there one at all?

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.

clearly not a horse posted:

I am exploring the STL, looking for a container type like a set, but sequenced, so that I can access elements of its members by it's position. More like an array of pointers, but I should not be able to have two of the same sort. Which one? Or is there one at all?

There isn't anything like that in the STL because there's no efficient way to implement it. You would either need to do a linear search through an array upon each insert or you would need to store the elements twice: once in a set and once in a vector. You could trivially roll your own using either technique, depending on whether space or time efficiency is more important to you.

Edit: I assume by "position" you mean insertion order? If you don't, then there may be something that will do this efficiently, just not in the STL.

Mr.Radar fucked around with this message at 17:31 on Jun 28, 2010

That Turkey Story
Mar 30, 2003

clearly not a horse posted:

I am exploring the STL, looking for a container type like a set, but sequenced, so that I can access elements of its members by it's position. More like an array of pointers, but I should not be able to have two of the same sort. Which one? Or is there one at all?

Is there a reason you can't just use an iterator or a pointer to the element rather than an integer position?

OddObserver
Apr 3, 2009

Mr.Radar posted:

There isn't anything like that in the STL because there's no efficient way to implement it.You would either need to do a linear search through an array upon each insert or you would need to store the elements twice: once in a set and once in a vector. You could trivially roll your own using either technique, depending on whether space or time efficiency is more important to you.

Edit: I assume by "position" you mean insertion order? If you don't, then there may be something that will do this efficiently, just not in the STL.

Uhm, for insertion order, you just cross-link your hash/tree data structure with a doubly-linked list. Very small constant-factor overhead for all set operations, though of course it may be too much if the data structure is extremely hot. Heck, Java even provides one of these in its standard library (LinkedHashSet<E>)

If he means position based on a sort order, that's doable, too, by using a balanced tree (or a similar data structure) augmented by size of each subtree. It's O(log n) for every operation, of course, but that's unchanged from having this sort of container anyway, either.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
This is more of an IDE question than a c++ question, but does anyone know of a way to add a library to Dev-C++?

shrughes
Oct 11, 2008

(call/cc call/cc)

Captain Frigate posted:

This is more of an IDE question than a c++ question, but does anyone know of a way to add a library to Dev-C++?

Don't use Dev-C++. Seriously.

Get Visual C++ Express, or Visual Studio Express, or whatever they're calling it nowadays.

Seriously.

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.
It really is terrible.

Painless
Jan 9, 2005

Turn ons: frogs, small mammals, piles of compost
Turn offs: large birds, pitchforks
See you at the beach!

shrughes posted:

Don't use Dev-C++. Seriously.

I was writing a post starting with "How the hell do people keep finding that poo poo, anyway?" but apparently people still keep installing "unstable beta" versions of it (as opposed to unstable release versions), based on a quick search for "free c++ ide".

Sweeper
Nov 29, 2007
The Joe Buck of Posting
Dinosaur Gum

Painless posted:

I was writing a post starting with "How the hell do people keep finding that poo poo, anyway?" but apparently people still keep installing "unstable beta" versions of it (as opposed to unstable release versions), based on a quick search for "free c++ ide".

For free c++ ide I got Code::Blocks, Netbeans and VS Express, I guess my google is better than your google :p

xPanda
Feb 6, 2003

Was that me or the door?

rjmccall posted:

It doesn't say it's an unrecognized type, it says it's an incomplete type, which means it's been declared but not yet defined. And yes, this is because your headers have a cyclic depdendency.

If Chain.h absolutely requires SequenceProperty.h (or rather, absolutely requires Residue.h which absolutely requires SequenceProperty.h), you might have to abandon the one-class-per-header rule you've apparently been working with, or at least do some funky restructuring (e.g. putting out-of-line method definitions in "more derived" headers).

Yeah this is pretty much the conclusion I came to. Curiously that trace omits an intermediate include in there, which doesn't change anything but I find it odd. I guess if all these related classes require each other they might as well be bundled together, or I can try and find a way to prune some of the includes back to forward declarations. Or something. I wonder why MSVC allows it, though?

Thanks for the help! I'm going to go strangle the original author, brb...

On the topic of IDEs, I've recently been using Eclipse + CDT on Mac OS X, mostly because I was already using Pydev. Are there any real show-stoppers with this setup, other than a crappy compiler error parser?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
C++ [temp.res]p7: If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required.

Different compilers rely on this to different extents. MSVC is very permissive and does basically no checking until the template is instantiated. GCC checks some things but not others. Clang is very strict about requiring types to be complete. EDG-based compilers do different things depending on what mode you run them in.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

shrughes posted:

Don't use Dev-C++. Seriously.

Get Visual C++ Express, or Visual Studio Express, or whatever they're calling it nowadays.

Seriously.

So how is it done in Visual Studio Express?

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.
Assuming the latest version of VS: In the project's settings, add the path to the library's header files to "Additional Include Directories" under C++ Compiler Options, add the path to the library's .lib files to "Additional Library Directories" and the .lib's name to "Additional Dependencies" under Linker Options. If the library is a dll, under "Debugging" add Path=$(Path);Path/To/Your/DLL/Directory to "Environment" or copy the dll to your output directory.

Some of the names might be different, I'm going off the top of my head.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Mustach posted:

Assuming the latest version of VS: In the project's settings, add the path to the library's header files to "Additional Include Directories" under C++ Compiler Options, add the path to the library's .lib files to "Additional Library Directories" and the .lib's name to "Additional Dependencies" under Linker Options. If the library is a dll, under "Debugging" add Path=$(Path);Path/To/Your/DLL/Directory to "Environment" or copy the dll to your output directory.

Some of the names might be different, I'm going off the top of my head.

Now what if I don't have an actual project or anything, just a .cpp that I need to compile with a custom library? It doesn't seem to like me doing any kind of debugging without setting up a project or anything? (I'm not very experienced with c++ and probably won't be doing too much with it after this).

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Captain Frigate posted:

Now what if I don't have an actual project or anything, just a .cpp that I need to compile with a custom library? It doesn't seem to like me doing any kind of debugging without setting up a project or anything? (I'm not very experienced with c++ and probably won't be doing too much with it after this).
In Visual Studio (and most IDEs for that matter), you need to have created a project first. In Unixland you can simply invoke g++ from the command line to compile a single file; MVCC might have a command-line frontend, too, but I don't know.

If you're really dead set against creating projects just to compile one-source-file programs, cygwin is always an option.

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.

Dijkstracula posted:

MVCC might have a command-line frontend, too, but I don't know.
It's called cl. It's not like making a project is difficult, but here's something that might work (I'm sure there are more flags needed):
code:
cl /link your.lib /IPath/To/Headers your_code.cpp
Running the "Visual Studio [year] Command Prompt" from the start menu will add cl to your path.

Just like before, if the library is a dll, it has to be in the runtime path in order to load it.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it

Dijkstracula posted:

In Visual Studio (and most IDEs for that matter), you need to have created a project first. In Unixland you can simply invoke g++ from the command line to compile a single file; MVCC might have a command-line frontend, too, but I don't know.

If you're really dead set against creating projects just to compile one-source-file programs, cygwin is always an option.

It's not so much that I'm dead set against anything, I just don't know how to do these things. If there's a simple way to make a project that wouldn't mess with the code that I already have that would give me a way to add this library that I need and compile, that's certainly good enough.

Adbot
ADBOT LOVES YOU

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.

Captain Frigate posted:

If there's a simple way to make a project that wouldn't mess with the code that I already have that would give me a way to add this library that I need and compile, that's certainly good enough.
File > New Project, pick command-line or window, check the "empty project" box, click finish. Then, Project > Add Existing resource and select your cpp file.

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