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
Star War Sex Parrot
Oct 2, 2003

That looks like a circular dependency to me.

Adbot
ADBOT LOVES YOU

OddObserver
Apr 3, 2009

Mr. Crow posted:

I'm learning gtest and c++ and can't wrap my head around how to do this, any guidance?

Lets say I have a templated class

code:
template<typename T>
class ItemBase : public OtherBase
{
public:
    T getFoo();
}
with multiple implementations. I want to test the logic in ItemBase<T> using type-parameterized tests so all implementors can test the shared logic. I've got it working fine with OtherBase because the parent is not templated; I'm having trouble getting my head wrapped around how to do this with the templated ItemBase<T> class. Help?


The primary issue I guess, is that I need to somehow have a member variable in my test fixture that's the concrete ItemBase<U>* type so I can reference it in it's tests, with the U being the pain in the rear end I can't figure out. It seems like only a single template parameter is allowed for classes deriving from ::testing::Test?

I am not sure I really understand your question, but TYPED_TEST and TYPED_TEST_CASE may be of use.
https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
(Or alternatively TYPED_TEST_P)

Mr. Crow
May 22, 2008

Snap City mayor for life

OddObserver posted:

I am not sure I really understand your question, but TYPED_TEST and TYPED_TEST_CASE may be of use.
https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
(Or alternatively TYPED_TEST_P)

The question is thus, how do I create type-parameterized tests for a templated class?

Type-Parameterized Tests seem to be what I want, but they only accommodate a single parameter (e.g. the derived class) so it seems to not work for templated types (e.g. the templated base class being tested), and I'm not seeing an alternative solution in their documentation.

gonadic io
Feb 16, 2011

>>=
I've installed the OSI library using this [url=http://www.coin-or.org/download/binary/CoinAll/COIN-OR-1.7.4-win32-msvc11.exe[/url] and I'm trying to compile a minimum working project using VS 2012 Ultimate.

The file, minimum.cpp, here here and it's in a win32 console application with precompiled headers off and character set to "Not Set".

The file initially had the #include statements underlined in red, but then I added the library and include directories to

"Linker > General > Additional Library Directories" and the "C/C++ > Additional Include Directories" in the project's Configuration Properties respectively. The red underlines went away.

However, when trying to build (debug or release mode) I get lots (9) of errors like:

Error 1 error LNK2019: unresolved external symbol "public: virtual __thiscall OsiSolverInterface::~OsiSolverInterface(void)" (??1OsiSolverInterface@@UAE@XZ) referenced in function "public: void __thiscall OsiClpSolverInterface::`vbase destructor'(void)" (??_DOsiClpSolverInterface@@QAEXXZ) C:\code\phd\osi\ConsoleApplication1\ConsoleApplication1\MinimumOSI.obj MinimumOsi


I added the /VERBOSE option to the build so that it'd list all the libraries that it's searching for. However, none of the libraries I've added (as mentioned above) show up in the output at all.

If the red underlines went away, does that mean that VS recognises the library files, so why won't the linker?

nielsm
Jun 1, 2009



AlsoD posted:

If the red underlines went away, does that mean that VS recognises the library files, so why won't the linker?

No, just that the IDE found some header files defining the names. It never looks past that, specifically does not look into what might happen during link.

You probably also need to add the actual library names to the configuration.

raminasi
Jan 25, 2005

a last drink with no ice
The option you want is in Linker > Input (if I'm remembering correctly). Add actual .lib names, not just directories.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
http://isocpp.org/files/papers/N4174.pdf Bjarne being Bjarne

gonadic io
Feb 16, 2011

>>=

nielsm posted:

You probably also need to add the actual library names to the configuration.

GrumpyDoctor posted:

The option you want is in Linker > Input (if I'm remembering correctly). Add actual .lib names, not just directories.

Thank you. Is there a way to tell which .lib files I want? They're not in the same naming convention as the .hpp files. Failing that, would adding "path/to/dir/*.lib" work or do I really need to add all 39 (or some subset thereof) separately?

I've tried calling DUMPBIN /SYMBOLS but the output is unreadable and very long, I suppose I could write a batch script to search through it all for the symbols I want, if needed.

nielsm
Jun 1, 2009



AlsoD posted:

Thank you. Is there a way to tell which .lib files I want? They're not in the same naming convention as the .hpp files. Failing that, would adding "path/to/dir/*.lib" work or do I really need to add all 39 (or some subset thereof) separately?

I've tried calling DUMPBIN /SYMBOLS but the output is unreadable and very long, I suppose I could write a batch script to search through it all for the symbols I want, if needed.

The short version is "all of them" and "possibly also including those in the intel subdir".
As long as you only have libraries for one platform/compiler settings combination in a single directory, including unneeded ones rarely hurts, since modern linkers usually avoid linking code never called by anything.

The long version is that you should be using a build script that calls the included pkg-config.exe with appropriate environment and parameters and have it return a list of libraries needed.

gonadic io
Feb 16, 2011

>>=
That did the trick, I have it compiling (but not running yet of course) now. Visual Studio certainly seems very heavy duty and intimidating compared to the CLI compiling of small projects that I'm used to.

gonadic io
Feb 16, 2011

>>=
Now with regards to getting it running: the installer for the library (linked above) installed libmmd.lib, but no libmmd.dll.

When the VS option "runtime library" is set to /MD (multithreaded dynamic), the generated executable will crash with "The program can't start because libmmd.dll is missing from your computer".

When the option is set to /MT (presumably multithreaded static), the compiler will fail with a whole bunch of "mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease'" errors.

Is it possible that the provided binaries were compiled dynamically but only the static libraries were included with the distribution? Can I generate a .dll from a .lib file? Looking around, libmmd seems to be part of intel's fortran compiler which I'm certainly not about to buy.

raminasi
Jan 25, 2005

a last drink with no ice
The runtime library isn't the issue - leave it set to multithreaded dynamic. I'm guessing that libmmd.dll is a redistributable library, which means you can get it freely without having to buy the compiler. You might try one of these.

gonadic io
Feb 16, 2011

>>=

GrumpyDoctor posted:

The runtime library isn't the issue - leave it set to multithreaded dynamic. I'm guessing that libmmd.dll is a redistributable library, which means you can get it freely without having to buy the compiler. You might try one of these.

That was exactly it thanks, it's now working perfectly. Christ I wish I'd asked here a week ago.

raminasi
Jan 25, 2005

a last drink with no ice
Don't feel too bad. Whoever built that installer you used messed up; the whole point of redistributable libraries is to redistribute them.

e: Actually, come to think of it, it might have but just not put it in your PATH.

raminasi fucked around with this message at 16:14 on Oct 14, 2014

gonadic io
Feb 16, 2011

>>=
There certainly wasn't any dll files included with the install (of the original library, COIN-OR) whatsoever.

hooah
Feb 6, 2006
WTF?
I feel like a doofus because I've apparently forgotten how to use stringstreams. Why does this cause pName to end up as -52 (a capital "I" with an accent on it) and then size to be 0 when I type "Request A 1024"?

C++ code:
string input = " ";
string discard = "";
string request = "";
string type = "";
char pName;
long size = 0;
// Loop to get input
while (input != "")
{
	cout << "To make a request, do 'Request <ProcessName> <Size>'.\n"
		<< "To release a process, do 'Release <ProcessName>.\n"
		<< "To finish, type 'done'." << endl;
	cin >> request;
	stringstream requestStream(request);
	requestStream >> type >> pName;
	if (type == "Request")
	{
		requestStream >> size;
	}
}

FamDav
Mar 29, 2008

hooah posted:

I feel like a doofus because I've apparently forgotten how to use stringstreams. Why does this cause pName to end up as -52 (a capital "I" with an accent on it) and then size to be 0 when I type "Request A 1024"?

C++ code:
string input = " ";
string discard = "";
string request = "";
string type = "";
char pName;
long size = 0;
// Loop to get input
while (input != "")
{
	cout << "To make a request, do 'Request <ProcessName> <Size>'.\n"
		<< "To release a process, do 'Release <ProcessName>.\n"
		<< "To finish, type 'done'." << endl;
	cin >> request;
	stringstream requestStream(request);
	requestStream >> type >> pName;
	if (type == "Request")
	{
		requestStream >> size;
	}
}

"cin >> request" breaks at whitespace. you want getline. also print out pName before and after you attempt to read into it from the stringstream.

stringstreams silently fail :(

FamDav fucked around with this message at 20:20 on Oct 14, 2014

hooah
Feb 6, 2006
WTF?

FamDav posted:

"cin >> request" breaks at whitespace. you want getline. also print out pName before and after you attempt to read into it from the stringstream.

stringstreams silently fail :(

Ahh, getline, thanks! (And I know I didn't initialize pName; I temporarily forgot how to represent the null character.)

MutantBlue
Jun 8, 2001

FamDav posted:

stringstreams silently fail :(

It's trivial to test for failure...

C++ code:
if (!(requestStream >> type >> pName)) {
	cerr << "stringstream extract failed\n";
	exit(OMG_BUTTES);
}

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
I have never understood the sort of thinking that would end up with iostream as an API.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Suspicious Dish posted:

I have never understood the sort of thinking that would end up with iostream as an API.

"Let's design an API purely to show off how powerful our operator overloading feature is"

Baron Bifford
May 24, 2006
Probation
Can't post for 2 years!
I'm trying to program a Linked List in C++. This is part of my code:

C++ code:
class LinkedList
{
    private:
    class Element
    {
        public:
        Element* ptr_next;
        int val ;
        Element() ;
    };

    Element* ptr_first;
    Element* ElementAt(int);
};

Element* LinkedList::ElementAt(int index)
{
    Element* e = ptr_first;

    for (int i = 0; (i < index) && (e != NULL); i++)
    {
        e = e->ptr_next;
    }
    return e;
}
The compiler has a problem with the line Element* LinkedList::ElementAt(int index). It returns an error: "'Element' does not name a type".

I found that if I cut the implementation for that function and pasted it within the class declaration, it compiles, ie if I do this:

C++ code:
class LinkedList
{
    private:
    class Element
    {
        public:
        Element* ptr_next;
        int val ;
        Element() ;
    };

    Element* ptr_first;
    Element* ElementAt(int index)
    {
        Element* e = ptr_first;

        for (int i = 0; (i < index) && (e != NULL); i++)
        {
            e = e->ptr_next;
        }
        return e;
    }
};
I do not like this solution, as I'd like to keep the implementation and the declarations separate. How do I solve this problem?

Nippashish
Nov 2, 2005

Let me see you dance!
You need to call it LinkedList::Element in the return type of the definition.

hooah
Feb 6, 2006
WTF?
Scope resolution operator:
LinkedList::Element* LinkedList::ElementAt(int index){};

MrPablo
Mar 21, 2003

Baron Bifford posted:

I'm trying to program a Linked List in C++. This is part of my code:

C++ code:
class LinkedList
{
    private:
    class Element
    {
        public:
        Element* ptr_next;
        int val ;
        Element() ;
    };

    Element* ptr_first;
    Element* ElementAt(int);
};

Element* LinkedList::ElementAt(int index)
{
    Element* e = ptr_first;

    for (int i = 0; (i < index) && (e != NULL); i++)
    {
        e = e->ptr_next;
    }
    return e;
}
The compiler has a problem with the line Element* LinkedList::ElementAt(int index). It returns an error: "'Element' does not name a type".

I found that if I cut the implementation for that function and pasted it within the class declaration, it compiles, ie if I do this:

C++ code:
class LinkedList
{
    private:
    class Element
    {
        public:
        Element* ptr_next;
        int val ;
        Element() ;
    };

    Element* ptr_first;
    Element* ElementAt(int index)
    {
        Element* e = ptr_first;

        for (int i = 0; (i < index) && (e != NULL); i++)
        {
            e = e->ptr_next;
        }
        return e;
    }
};
I do not like this solution, as I'd like to keep the implementation and the declarations separate. How do I solve this problem?

The compiler is telling you it doesn't know what an "Element*" is in that scope. LinkedList::ElementAt should return LinkedList::Element* instead of Element*, and ptr_first in LinkedList::ElementAt should be declared as a
LinkedList::Element* instead of Element*.

Baron Bifford
May 24, 2006
Probation
Can't post for 2 years!
Doh. Seems so obvious now.

Mr. Crow
May 22, 2008

Snap City mayor for life
Is there a library (standard or otherwise) to transform character literals to html special characters? E.g. something like \n to <br/>?

nielsm
Jun 1, 2009



Mr. Crow posted:

Is there a library (standard or otherwise) to transform character literals to html special characters? E.g. something like \n to <br/>?

That's a really bad example.
Mainly because <br> is not an SGML entity, but a tag.

Maybe try an XML library. Or just a dumb string-replace, you can get a data file here: http://www.w3.org/TR/html5/entities.json


If you instead want to transform human-readable-ish text into HTML with decent formatting, maybe try Markdown.

hooah
Feb 6, 2006
WTF?
I'm doing a project that pretends to implement the buddy system of memory allocation. I want to store the address and process name (a char) in a data structure that gets sorted by address whenever a new element is added. Here's the class that should do that:

C++ code:
#pragma once

#include <vector>
#include <algorithm>

// Represents a process
class Process
{
public:
	Process(int a, char l) : mAddress(a), mLabel(l) {}
	const char GetLabel() const { return mLabel; }
	const long GetAddress() const { return mAddress; }

private:
	char mLabel = '\0';
	long mAddress = 0;
};


// Comparison function for sorting mAllocated
	bool comp(const Process *l, const Process *r)
	{
		return l->GetAddress() < r->GetAddress();
	}


// Keeps track of assigned blocks by address
class Allocated
{
public:
	Allocated();
	~Allocated();
	// Add an address to the list, then sort it to make sure it goes to the right place
	void Add(int a, char l) { mAllocated.emplace_back(a, l); std::sort(mAllocated.begin(), mAllocated.end(), comp); }
	// Remove an address from the list
	void Remove(char l) { mAllocated.erase(std::remove(mAllocated.begin(), mAllocated.end(), l), mAllocated.end()); }

private:
	// Store the addresses
	std::vector<Process*> mAllocated;
};
The problem I'm having is that as-is, the compiler (MSVC) complains that "error C2446: '==' : no conversion from 'int' to 'Process *'" in the algorithm header. I also tried wrapping the function in a struct as I've done before with an std::priorty_queue:
C++ code:
// Comparison function for sorting mAllocated
struct comp{
	bool operator()(const Process *l, const Process *r)
	{
		return l->GetAddress() < r->GetAddress();
	}
};
When I do this, the compiler says "error C2275: 'comp' : illegal use of this type as an expression" on the line where I sort the vector. What am I not getting?

Vanadium
Jan 8, 2005

Probably just comp() in std::sort(mAllocated.begin(), mAllocated.end(), comp()).

raminasi
Jan 25, 2005

a last drink with no ice
MSVC's emplace_back doesn't work right and might be causing your problem.

hooah
Feb 6, 2006
WTF?

Vanadium posted:

Probably just comp() in std::sort(mAllocated.begin(), mAllocated.end(), comp()).

Nope. With the struct version, I get the "no conversion from 'int' to 'Process *'" error, and with the plain function version, I get an error that 'comp' does not take 0 arguments.

GrumpyDoctor posted:

MSVC's emplace_back doesn't work right and might be causing your problem.

FFS. I'll give this a shot.

GeneralZod
May 28, 2003

Kneel before Zod!
Grimey Drawer
The usage of emplace_back there would be fine if mAllocated were a

code:
std::vector<Process>
but it is a

code:
std::vector<Process*>

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!

hooah posted:

I'm doing a project that pretends to implement the buddy system of memory allocation. I want to store the address and process name (a char) in a data structure that gets sorted by address whenever a new element is added. Here's the class that should do that:
You could just use a std::set for this, with a comparison 'struct' (like you used for a priority_queue) specified in the declaration. 'set' is a horrible misnomer for this template because (even when it's not a red-black tree) the spec of std::set is that it is an ordered thing, which a mathematical set is not. But this is a pretty good match for what you want.

Since your particular purpose has more to do with ordering and single insertions, and less to do with random access, a set isn't entirely appropriate, but it would be better than the append-then-sort operation you're doing, especially since you're doing it on a vector. And it would be less error prone because you can't ever neglect to keep it properly ordered.

FamDav
Mar 29, 2008

GeneralZod posted:

The usage of emplace_back there would be fine if mAllocated were a

code:
std::vector<Process>
but it is a

code:
std::vector<Process*>

what crazy carl said

you either need to store a shared_ptr, unique_ptr, or the actual type itself. unless you start sharing the data around, you probably just want vector<Process>

hooah
Feb 6, 2006
WTF?

roomforthetuna posted:

You could just use a std::set for this, with a comparison 'struct' (like you used for a priority_queue) specified in the declaration. 'set' is a horrible misnomer for this template because (even when it's not a red-black tree) the spec of std::set is that it is an ordered thing, which a mathematical set is not. But this is a pretty good match for what you want.

Since your particular purpose has more to do with ordering and single insertions, and less to do with random access, a set isn't entirely appropriate, but it would be better than the append-then-sort operation you're doing, especially since you're doing it on a vector. And it would be less error prone because you can't ever neglect to keep it properly ordered.

This sounds like a good approach, thank you. We really only did non-vector collections for a couple weeks (a year ago), so I don't think about them enough. I'll give this a shot tonight.

hooah
Feb 6, 2006
WTF?
Ok, set seems like it might be working better, but I'm having trouble with my ::remove function. Since I'm putting objects into the set, I can't just do mySet.erase(someProcess); I have to search for the proper object with an iterator and use that to erase something. The problem I have now is defining the return type for my search function. I figured I'd just have the compiler do it and say decltype(mAllocated.begin()) search(Process);, but I get an error "C2228: left of '.begin' must have class/struct/union". Then on my return line ("Return iter"), I get "C2440: 'return': cannot convert from 'std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<Process>>>' to 'int'". The last error especially doesn't make much sense to me since 'int' definitely shouldn't be the type of mAllocated.begin(), but I guess it is?

raminasi
Jan 25, 2005

a last drink with no ice
Why are you writing your own search function?

Or, for that matter, your own erase function?

hooah
Feb 6, 2006
WTF?
Because when the client program wants to erase something, it'll ideally just give a char that is the process's name, and unless I'm misunderstanding it, set::find takes the same type as what the set stores. I suppose I could re-write the client program to create the Process objects itself, but I'd hoped to avoid having the client know about what seems like internal implementation details.

Adbot
ADBOT LOVES YOU

raminasi
Jan 25, 2005

a last drink with no ice

hooah posted:

Because when the client program wants to erase something, it'll ideally just give a char that is the process's name, and unless I'm misunderstanding it, set::find takes the same type as what the set stores. I suppose I could re-write the client program to create the Process objects itself, but I'd hoped to avoid having the client know about what seems like internal implementation details.

Well, in that case, you still don't need to roll your own search.

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