473,796 Members | 2,603 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Expression: map/set iterators incompatible

Me and my colleagues have been working on a problem since yesterday and can’t
seem to find a solution to it. It relates in a good measure to iterators and
the way we’re using them in our project. I will first give you a little
introduction to our main task. We had at our hands entire modules which were
written in C++. These were to communicate with a stack written in C, and in
turn act as a layer between the C code and C# code used in another
application.

Whoever had developed the C++ code, was building it using makefiles in the
cygwin shell, as the condition then (for whatever reasons) had been that the
code remains ANSI compatible. So the C++ code was being built using
compilers/linkers for cygwin, cygmingw, and vc7.1. A free tool called SWIG[0]
was being used to generate an export file to be compiled with the C++ code as
well as a full C# wrapper of all the C++ classes and functions. (Essentially
SWIG generates a flattened interface to all the C++ classes and then builds
the objects in C# and uses pinvoke with a pointer to access the C++ classes).
In our main C# application, we references these C# wrapper dlls in projects
depending on the functionality and all seemed to work.

Recently though, our project team decided that we should have all the code
in the Visual Studio environment, and we felt strongly that it would enable
us to debug the unmanaged code, if there is a need to, and thus have better
control over code maintainence. Furthermore, we decide to move over to the
VC8.0, which seemed the most logical thing to do.

Implications – First of all, we felt that the effort involved in translating
the makefile script to VS properties was considerable. Even though the
makefiles were done very intelligenty, they also had very specific
instructions, and these were often masked under many layers of variables. A
lot of time and energy led us finally to having a VS 2005 solution with all
the C++ projects, their corresponding C++ test console applications, C#
projects which contained the files automatically generated with SWIG, and
finally the C# unit test projects to test these C# projects.

In addition, we could also debug down to the C++ code, which was
encouraging. We were able to generate the C++ dlls and the C# wrapper dlls as
cygwin. However, with the test modules, we have run into this seemingly
unsolvable problem.

This test aims first at establishing a connection with a server on a real
device and then to compare some characteristics with it. The error we get is:

Debug Assertion Failed!

Program: C:\....\Test.ex e
File: C:\Program Files\Microsoft Visual Studio 8\VC\include\xt ree
Line: 293

Expression: map/set iterators incompatible

For information on how your program can cause an assertion failure, see the
Visual C++ documentation on asserts.

(Please Retry to debug the application).

As for the code samples, please bear in mind the following:

1. We are using the following typemaps

// Kind of cached item.
enum RefKind {...};

// Vector of cached items of the same kind.
typedef std::vector<str ing> RefsVec;

typedef std::map<RefKin d, RefsVec> KindRefsMap;
typedef std::map<CoreTy pes::ObjectName , KindRefsMap> LN2KindMap;
typedef std::map<CoreTy pes::ObjectName , LN2KindMap> LD2LNMap;

2. LD2LNMap is instantiates as:
// Cache for References (names). Created per LD the first time a
// directory service is called for an element belonging to the LD.
// Format: {ldName; {lnName; {CDC|...|DS; vectorOfObjRefs }}}
LD2LNMap dirCache;

3. The function that was initially called:

public void useGetDataSetDi rectory() {
Console.WriteLi ne("");
Console.WriteLi ne("------ useGetDataSetDi rectory ----------");
foreach(LDRefer ence ld in _server.GetServ erDirectoryLogi calDevices()) {
Console.WriteLi ne("LD: " + ld.getRef());
foreach(LNRefer ence ln in _server.GetLogi calDeviceDirect ory(ld)) {
.......
}
}
}
4. After getLD returns null, hasLDName throws the exception and the above
assertion failure message is displayed:

// getLD()
CoreAcsi::Namin gCache::LD2LNMa p::const_iterat or
CoreAcsi::Namin gCache::getLd(c onst CoreTypes::Obje ctName& ldName) const
{
LD2LNMap::const _iterator it1 = dirCache.find(l dName);
if (it1 != dirCache.end()) {
return it1;
}
return NULL;
}

// hasLDName
CoreTypes::P_BO OLEAN
CoreAcsi::Namin gCache::hasLDNa me(const CoreTypes::Obje ctName& ldName) const
{
return (getLd(ldName) != NULL);
}
Apr 26 '06 #1
6 10971
Wow, this was an arcane one!

The short answer is that you can't compare iterators that don't point to the
same collection. In your hasLDName function, the runtime is converting NULL
to type LD2LNMap::const _iterator& so that the != comparison can take place,
but since the NULL doesn't actually point to the same LD2LNMap object that
the getLd function returned, you get an error.

This is hard to explain, so bear with me.

The getLd function returns an object of type LD2LNMap::const _iterator. This
const_iterator' s operator!= function is called to compare the const_iterator
to the value NULL.

For the comparison to work, the NULL must be converted to type
const_iterator& . The runtime can create a temporary const_iterator object,
but this temporary iterator is not actually pointing to anything (at least
not anything meaningful).

It turns out that STL maps are based on red-black binary trees that are
defined in the <xtree> header. The const_iterator: :operator== function for
these trees (operator!= is implemented simply as the negation of operator==)
first tests to see that the two iterators being compared point to the same
tree.

Since the temporary const_iterator object doesn't actually point to any tree
at all, the test fails, and you get the error "map/set iterators
incompatible".

Therefore, one way to write your hasLDName function would be:

// I don't know if you've assigned special "true" and "false" values to your
CoreTypes::P_BO OLEAN type, so I am illustrating with the primitive bool type.

bool
CoreAcsi::Namin gCache::hasLDNa me(const CoreTypes::Obje ctName& ldName) const
{
LD2LNMap::const _iterator it1 = dirCache.find(l dName);
if (it1 != dirCache.end())
{
return true;
}

return false;
}

Hopefully this makes some sense. If not, maybe someone else with a little
more experience with STL can help.

Sean
Apr 27 '06 #2
Thanks for the prompt response Sean. Your analysis of the problem was dead
on; after going back and looking through the code again, we see that
comparing an iterator with NULL will always through an exception.
Unfortunately, since this was allowed in previous versions of the STL
included with Visual Studio (and also with GCC), the code we are working with
makes heavy usage of (iterator == NULL). Just curious if you or anyone else
might have suggestions as to the best way to approach this problem.

Should we be looking at changing all the places in our code that uses
iterator == NULL [possibly substituting for iterator == container.end()]? Or
is there another way to default to the old behaviour?
Apr 27 '06 #3
Shiraz wrote:
Thanks for the prompt response Sean. Your analysis of the problem was dead
on; after going back and looking through the code again, we see that
comparing an iterator with NULL will always through an exception.
Unfortunately, since this was allowed in previous versions of the STL
included with Visual Studio (and also with GCC), the code we are working with
makes heavy usage of (iterator == NULL). Just curious if you or anyone else
might have suggestions as to the best way to approach this problem.

Should we be looking at changing all the places in our code that uses
iterator == NULL [possibly substituting for iterator == container.end()]? Or
is there another way to default to the old behaviour?


Iterators are not pointers and should only be compared with other
iterators of the same type. If you are looking for an iterator which
says that you are not accessing anything valid, it should be set to the
end of the container to which the iterator belongs and you can check if
it is accessing a valid value by writing "if ( myIterator ==
myContainer.end () )". This is the standard notation for checking if an
iterator is accessing a valid value or not when looping through
containers. Checking an iterator against 0 ( NULL ) is just incorrect C++.
Apr 27 '06 #4
"Shiraz" wrote:
Unfortunately, since this was allowed in previous versions of the STL
included with Visual Studio (and also with GCC), the code we are working with
makes heavy usage of (iterator == NULL).
Every time I see a NULL being assigned or compared to something that is not
a pointer, I force myself to stop and ask why. At the very minimum it is
unclear coding (if the other object is a number, compare it to 0, not NULL!)
and a potentially unnecessary creation of a temporary object.
Should we be looking at changing all the places in our code that uses
iterator == NULL [possibly substituting for iterator == container.end()]? Or
is there another way to default to the old behaviour?


It depends on what's being done with the iterators at the time of each
comparison. If the iterator was created as a result of calling the find
function of a map, then the iterator is guaranteed to either point to an
element or to container.end, so the comparison iterator == container.end
would be a valid test of whether the find function actually found something.

Other iterators might require different tests. (Reverse iterators are the
first example that comes to mind. There might be others.)

Another option might be to have functions like your getLd function return
pointers to iterators (and NULL if the desired object is not found), and then
compare the iterator * to NULL. Whether this would be desirable or not
depends to a large degree on the other code in your project. I'm unsure of
any performance impact. On one hand, there would be more pointer derefencing
occurring when you needed to use the iterator. On the other hand, you would
eliminate all the temporary object creation that happens every time NULL has
to be converted to an iterator type.
Apr 27 '06 #5
"Edward Diener" wrote:
Iterators are not pointers and should only be compared with other
iterators of the same type.


Strictly speaking, iterators should only be compared to other iterators of
the same type whose containers are the same container as the first iterator.

map<int, int> m1;
map<int, int> m2;
map<int, int>::iterator i1 = m1.begin();
map<int, int>::iterator i2 = m2.begin();

if (i1 == i2) {...} // Error! - iterators don't point to same map object

Sean
Apr 27 '06 #6
Sean M. DonCarlos wrote:
"Edward Diener" wrote:
Iterators are not pointers and should only be compared with other
iterators of the same type.


Strictly speaking, iterators should only be compared to other iterators of
the same type whose containers are the same container as the first iterator.


I agree. Thanks for the qualification.
Apr 27 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1338
by: Steven Bethard | last post by:
So I was looking at the Python 3.0 wiki (http://www.python.org/moin/Python3_2e0) and noticed that one of the major changes would be that builtin classes and functions would take and return iterators instead of lists. Along these same lines, I'm wondering if we could also add the feature that a *expression parameter produces an iterable instead of a tuple. Right now, using the *expression syntax with an iterable causes that iterable to...
10
2217
by: Steven Bethard | last post by:
So, as I understand it, in Python 3000, zip will basically be replaced with izip, meaning that instead of returning a list, it will return an iterator. This is great for situations like: zip(*) where I want to receive tuples of (item1, item2, item3) from the iterables. But it doesn't work well for a situation like: zip(*tuple_iter)
4
2693
by: kalita | last post by:
Hi All, typedef std::list<int> Cont; void f(Cont &c1, Cont &c2) { Cont::iterator it = c1.begin(); c1.swap(c2); it == c2.begin(); // is this ill formed? }
2
2875
by: Jean | last post by:
Hello everyone, I was having the following problem with a query, and after failing to find a similar solution on these newsgroups I decided to post here. I am quite new to Access, so would appreciate any help/pointers in the right direction. The problem is that I keep getting the error to the likes of "Data types in the criterion expression are incompatible" when the query runs.
2
2355
by: ma740988 | last post by:
typedef std::vector < std::complex < double > > complex_vec_type; // option1 int main() { complex_vec_type cc ( 24000 ); complex_vec_type dd ( &cc, &cc ); } versus
18
7857
by: njgreen2001 | last post by:
I thought the length of this might give me problems. Any suggestions on how to shorten it? Expression: =IIf(="A Pos" And ="A Pos",(DLookUp("","")), IIf(="A Pos" And ="A Neg",(DLookUp("","")), IIf(="A Pos" And ="B Pos",(DLookUp("","")), IIf(="A Pos" And
19
2137
by: fungus | last post by:
I mentioned earlier to day that I was moving some code from VC++6 to VC++2005 and having trouble with the new iterators. There's all sorts of problems cropping up in the code thanks to this change. a) With pointer-iterators you could set an iterator to null to mark it as invalid, you can't do that any more. b) You can't use const_cast with iterators.
15
4851
by: Matt | last post by:
Hi There, Can anyone explain me the real advantages of (other than syntax) lambda expressions over anonymous delegates? advantage for one over the other. delegate int F(int a); F fLambda = a =a++; F fAnonymous = delegate(int a) { return a++; }; fLambda(1);
1
23438
by: urkel | last post by:
Hi everyone, I critically need help to solve this problem related to pointer in C++ Basically, I have a C/C++ program "retardselfenerg" calling a Fortran 90 subroutine "surfGF4.f90". i am so doubtful if my definitions of pointer variables and their use in calling function are correct. #include<bla bla bla......h> #include<bla bla bla.h> double surfGF4_(double*, double*, double*, double*, double*, double*, double*, double*, double*); ...
0
9535
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10242
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10021
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7558
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5453
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5582
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4127
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3744
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2931
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.