Solved

function objects with internal state in Visual C++

Posted on 2001-06-14
18
216 Views
Last Modified: 2013-12-14
I want to sort an STL list using a function object with a state.  The function object  needs a pointer to determine which object (CContourPortionMatch) is greater.

Problem:

The list.sort(..) ignores the (initialised) function object passed to it and creates its own (uninitialised) object using the default constructor.

Questions:

1) Is this a dead end? Is there a way I can get list.sort(..) to work with function objects that have states using Microsoft's STL (I'm hopeful)?
2)Is it worthwhile to switch to a different STL library for windows?  Is there a bug-free (or less buggy) one out there that I could drop in?

Code:

CContour *pContour = (*iContour).first;
ASSERT_VALID(pContour);

///////////////
// Sort List //
///////////////

//Create (initialised)function object
std::greater<CContourPortionMatch> Test2(pContour);

//Sort lowest to highest
//(bug: creates own object here using default constructor of greater<CContourPortionMatch>)
pList->sort(Test2);


Where greater<CContourPortionMatch> is defined as:

////////////////////////////////
// Function object definition //
////////////////////////////////
// (see http://support.microsoft.com/support/kb/articles/Q265/1/09.ASP 
// for bug that requires the function object to be defined
// this way)

template<>
class std::greater<CContourPortionMatch>  : public binary_function<CContourPortionMatch ,CContourPortionMatch, bool>
{
public:
  //Constructor I want to use
  std::greater<CContourPortionMatch>(CContour * pContour)
     { m_pContourToUse = pContour;};

  // Constructor that is called by sort(and is necessary for compilation)
  std::greater<CContourPortionMatch>() {m_pContourToUse =NULL;};

 //This function is called by the sort using an uninitialised object
 bool operator()(const CContourPortionMatch & Match1, const CContourPortionMatch &Match2) const
{
  //Get start indices for contour in matches
  int bStartIndex1 = Match1.GetStartIndex(m_pContourToUse);
  int bStartIndex2 = Match2.GetStartIndex(m_pContourToUse);

 return (bStartIndex1 < bStartIndex2);
}

//The contour to use for comparison of starting indices
//Must be valid for comparison to work (bug: is never valid)
CContour * m_pContourToUse;
};
0
Comment
Question by:PeteK
  • 6
  • 6
  • 6
18 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 6192165
A maybe silly suggestion (more like a workaroung while I'm thinking about all that):

You could make 'm_pContourToUse' static for the functor class and use it like


//Create (initialised)function object
std::greater<CContourPortionMatch>::m_pContourToUse = pContour;
std::greater<CContourPortionMatch> Test2(pContour);

//Sort lowest to highest

pList->sort(Test2);

0
 

Author Comment

by:PeteK
ID: 6192304
jkr, I tried:

static CContour * m_pContourToUse;

but it produced a linker error:

ContourPortionMatcher.obj : error LNK2001: unresolved external symbol "public: static class CContour *  std::greater<class CContourPortionMatch>::m_pContourToUse" (?m_pContourToUse@?$greater@VCContourPortionMatch@@@std@@2PAVCContour@@A)

I think I'm in the market for a C++ compiler that has a good STL. Dinkumware? STLPort?




0
 
LVL 86

Expert Comment

by:jkr
ID: 6192355
>>jkr, I tried:
>>static CContour * m_pContourToUse;

You did that within the class declaration? If not, that would explain the error - I was thinking of

template<>
class std::greater<CContourPortionMatch>  : public binary_function<CContourPortionMatch ,CContourPortionMatch,
bool>
{
public:
 //Constructor I want to use
 std::greater<CContourPortionMatch>(CContour * pContour)
    { m_pContourToUse = pContour;};

 // Constructor that is called by sort(and is necessary for compilation)
 std::greater<CContourPortionMatch>() {m_pContourToUse =NULL;};

//This function is called by the sort using an uninitialised object
bool operator()(const CContourPortionMatch & Match1, const CContourPortionMatch &Match2) const
{
 //Get start indices for contour in matches
 int bStartIndex1 = Match1.GetStartIndex(m_pContourToUse);
 int bStartIndex2 = Match2.GetStartIndex(m_pContourToUse);

return (bStartIndex1 < bStartIndex2);
}

public:
static CContour * m_pContourToUse;
};


0
 

Author Comment

by:PeteK
ID: 6192390
I tried it in the class declaration but I got the linking error.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6192408
>>but I got the linking error

Hum hum - try a 'Rebuild All' that sometimes helps in these cases...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192442
Did you get the same exact error?
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192465
>>I think I'm in the market for a C++ compiler that has a good STL. Dinkumware? STLPort?

The reason why you're getting an error is because you have the implementation for m_pContourToUse static member in your *.cpp code.
You would have this problem regardless of what compiler you would use.
To my knowledge, there are no compilers that will correctly compile template code that has implementation in the *.cpp file.

To remove the error, implement m_pContourToUse in your *.h file, but make sure you put a header gaurd around it.
0
 

Author Comment

by:PeteK
ID: 6192468
I rebuilt everything and got the same error. The error goes away if I remove 'static' from the class declaration. Here is the complete output:

Linking...
CleftFinder.obj : error LNK2001: unresolved external symbol "public: static class CContour *  std::greater<class CContourPortionMatch>::m_pContourToUse" (?m_pContourToUse@?$greater@VCContourPortionMatch@@@std@@2PAVCContour@@A)
ContourPortionMatcher.obj : error LNK2001: unresolved external symbol "public: static class CContour *  std::greater<class CContourPortionMatch>::m_pContourToUse" (?m_pContourToUse@?$greater@VCContourPortionMatch@@@std@@2PAVCContour@@A)
SliceJoiner.obj : error LNK2001: unresolved external symbol "public: static class CContour *  std::greater<class CContourPortionMatch>::m_pContourToUse" (?m_pContourToUse@?$greater@VCContourPortionMatch@@@std@@2PAVCContour@@A)
Debug/CryoTactics.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192478
>>The error goes away if I remove 'static' from the class
declaration.

That's because static members have to be implemented outside of the class declaration.  If you want m_pContourToUse to be static, you need to add implementation for it.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:PeteK
ID: 6192483
Axter, I have the declaration of class std::greater<CContourPortionMatch> (with m_pContourToUse)  in the header file of CContourPortionMatch (ContourPortionMatch.h).

The call to pList->sort(Test2) code is in the .cpp file of another class (CSliceJoiner in SliceJoiner.cpp).
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192504
I'm not sure if you understand what I'm trying to say, so I'll give you an example, but it's a non template class example:

//My header file foo.h

class foo
{
 static int m_MyStaticMemeber;
 int m_MyNonStaticMemeber;//Don't need anything else for non-static members
};

//My source file foo.cpp

int foo::MyStaticMemeber; //Need this for static members
0
 
LVL 86

Expert Comment

by:jkr
ID: 6192507
OK, just to test the functionality (and to address the 'static' problem later), try and make it a global variable...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192514
FYI,
I had a type-O.  That should have been:
int foo::m_MyStaticMemeber; //Need this for static members

0
 
LVL 86

Accepted Solution

by:
jkr earned 200 total points
ID: 6192530
>>int foo::MyStaticMemeber; //Need this for static members

Hmm, I think Axter is right on this ( I hardly ever use static data members, so I missed it) - make

std::greater<CContourPortionMatch>::m_pContourToUse = pContour;

read

CContour* std::greater<CContourPortionMatch>::m_pContourToUse = pContour;


0
 

Author Comment

by:PeteK
ID: 6192537
Testing now...
0
 

Author Comment

by:PeteK
ID: 6192629
Thanks jkr and Axter. I appreciate it.

I added the static member implementation and it worked (and in the process discovered a bug in my code that may have interfered with the original problem).

Axter, I'll post a "points for Axter" transfer for you.

Thanks again.  Its good to have help from people who can see both the forest and the trees.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6192643
Welcome, and thanks for the points.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6192647
Thanx :o)

BTW: After thinking about that for a while, I really cannot imagine another way to achieve that...
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Writing a parser for java language 4 71
Copying WordPress Pages 5 76
Dynamically allocate memory 9 56
Best book to learn C++ 4 70
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

930 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now