Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

icc on linux errors

dajum
Novice
529 Views

Hi,

I have the following header TdMap.h that I use in a number of other classes to create maps.  This works fine on windows using VC, but trying to port it to linux using icc I get some errors that I don't understand.  Hoping it might be something obvious.  Here is the start of the header file:

#pragma once

#include <map>

template <class K, class T, class C>
class TdMap : public std::map< K, T, C >
{
public:

    bool isEmpty() const { return size() == 0 ? true : false; }
    int length() const { return (int) size(); }
    int entries() const { return (int) size(); }
    bool findValue( const K& key, T& r ) const
    {
        const_iterator i=find(key);
        if(i != end()) {
            r = i->second;
            return true;
        }
        return false;
    }
    bool findIter( const K& key, iterator &iter )
    {
        iterator i=find(key);
        if(i != end()) {
            iter = i;
            return true;
        }
        return false;
    }

the types for iterator and const_iterator get errors as being undefined in both the findValue function and findIter function (both argument list and inside).  But it appears to me that std::map does define them.  I find if I use std::iterator<std::bidirectional_iterator_tag, TdMap> for iterator then it does compile.  But I would like to use the typedef's that I do use on Windows so I don't need to modify all my sources. I'm using XE2011

Thanks!

 

0 Kudos
8 Replies
KitturGanesh
Employee
529 Views

You need a typename qualifier like: typename std::map<key, value>::iterator. So, in your code you may want to change to:  " typename std::map<K,T>::const_iterator i=find(key);"  and  then you can use i accordingly. Also, you need to do the same for the func parameter as well such as: "typename std::map<K,T>::iterator &iter".

_Kittur 

0 Kudos
dajum
Novice
529 Views

Thanks for the quick reply.  Can you explain why it has to have the full typename included.  Isn't "iterator" defined by the map class, and hence should be known within the scope of the TdMap class? This all compiles fine within Visual C without including the typename, but not in icc.  Similar problems result for using size() and resize(), that I know get resolved if I add std::map,  but that seems like it should be overkill.

Thanks!

Dave 

0 Kudos
KitturGanesh
Employee
529 Views

Hi,
Yes, what you say makes sense in that you're right the typedefs are defined in the map header and yes, it does work in MS cl. As I mentioned earlier just adding the type qualifier for the function parameter for iter should work and the reasons are as below when compiling with icc:

  • The error is output from prototype instantiation where the compiler (icc) cannot determine the actual type
  • Also, the reason the error doesn't show for the iterator used inside the function is 'cause, during real instantiation, the compiler knows the type and hence doesn't output the error.
  • Intel's compiler for Windows* and MS's cl doesn't give error and work. Reason, the prototype instantiation is not made for that.

I tried the same with g++ and it behaves the same way as icc, fyi.

_Kittur

0 Kudos
dajum
Novice
529 Views

Thanks Kittur for your time on this issue.  I still do not understand "why" icc can't determine the actual type during prototype instantiation since the scope should already be known, and the type has been previously defined within the scope. That to me seems to make MS cl a much better compiler.  But for now I will live with it while using icc.

Dave

0 Kudos
KitturGanesh
Employee
529 Views

Dave, with regard to Intel's complier on windows it behaves fine for this test case vs. MS cl.  Briefly, the two phase lookup is the name for the standard defined behavior for name lookup within the template code and some names are defined as dependent (rules are a bit confusing) and they must be looked up when instantiating the template and independent names looked up when parsing the template. This is a bit confusing for developers and so compilers sometimes tend not to implement to the standard and end up searching for template context and instantiation context accepting code which shouldn't per standard and is possible.  That said, prototype instantiation is a standard requirement on adding a typename. Also, there are cases for example MS may not do that way and can accept this case you indicate but may not where compiler may do prototype instantiation and such.  It's a little confusing but you may need to refer to standard doc on prototype instantiation to get more details. 

BTW, I did check with the developers and they came up with the same input as mentioned above as well.

_Kittur 

0 Kudos
Judith_W_Intel
Employee
529 Views

 

Yes the short answer is that the Microsoft compiler does not implement the C++ standard rule about lookup in template dependent base classes (sometimes called two-stage name lookup) but GNU and Clang do implement the rule.  Since our compiler must be compatible with the reference compiler on a particular platform it acts differently on Linux vs. Windows.

 

See:

http://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates/

http://stackoverflow.com/questions/11619122/argument-dependent-lookup-through-base-of-a-template-class  (section 11.9.2)

http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html

 

 

 

0 Kudos
dajum
Novice
529 Views

Kittur and Judith,

Thanks so much!  I now see the difference on the name lookup for dependent and non-dependent names.  I greatly appreciate the explanations. 

Dave

0 Kudos
KitturGanesh
Employee
529 Views

Pleasure's ours, Dave. I am also glad that Judy summarized the reasons so nicely (thanks Judy).

_Kittur

0 Kudos
Reply