views:

224

answers:

3

I have the following typedef's in my code:

typedef unsigned long int ulint;
typedef std::map<ulint, particle> mapType;
typedef std::vector< std::vector<mapType> > mapGridType;

particle is a custom class with no default constructor.

VS2008 gives me an error in this code:

std::set<ulint> gridOM::ids(int filter)
{
    std::set<ulint> result;
    ulint curId;
    for ( int i = 0; i < _dimx; ++i ) {
        for ( int j = 0; j < _dimy; ++j ) {
            // next line is reported to be erroneous
            for ( mapType::iterator cur = objectMap[i][j].begin(); cur != objectMap[i][j].end(); ++cur )
            {
                curId = (*cur).first;
                if ( (isStatic(curId) && filter != 2) || (!isStatic(curId) && filter != 1) )
                {
                    result.insert(curId);
                }
            }
        }
    }
    return result;
}

objectMap is an object of mapGridType. The error reads:

error C2512: 'gridOM::particle::particle' : no appropriate default constructor available
while compiling class template member function 'gridOM::particle &std::map<_Kty,_Ty>::operator [](const unsigned long &)'  
        with  
        [  
            _Kty=ulint,  
            _Ty=gridOM::particle  
        ]  
        .\gridOM.cpp(114) : see reference to class template   instantiation 'std::map<_Kty,_Ty>'   being compiled  
        with  
        [  
            _Kty=ulint,  
            _Ty=gridOM::particle  
        ]  

Correct me if I'm wrong, but the above code should not be making calls to map::operator[] at all. The first operator[] call is made to vector< vector<mapType> > and returns a vector<mapType>, the second is made to vector<mapType> and returns a mapType aka a map<ulint, particle>, and I only call begin() and end on that map. So why do I get an error trying to compile the operator[] for map?

+1  A: 

I'm not sure of my answer. But when you instanciate a template, the compiler implements all the functions defined in the template (even if they aren't used). So you get the error, even if there is no use of the function.

Could you give the complete error message?

EDIT With the full error message, you get the problem! As you told, your object has no default constructor. However, in order to use a map, you need the default constructor (as it is required by the function operator[] in order to build an instance when using a new key), even if you don't use the function, it will be implemented by the compiler.

Tristram Gräbener
Sorry, accidentally left off the first line of the error. Edited.
suszterpatt
Not true. Each class template definition in reality *defines* a template for the class type itself and *declares* a bunch of independent templates for its member functions. (Yes, each member function is an independent template). When you instantiate class template, member functions *don't* get immediately instantiated, until you actually call them or force their instantiation in some other way. So, until you actually call `std::map<>::operator[]` it must *not* get instantiated, even if you already instantiated `std::map<>` itself.
AndreyT
Regarding your edit. I'm actually editing code that was working before. The typedef's were the same, and the code compiled and ran even with no default constructor for `particle`. I'm fairly sure that templates get instantiated on a per-method basis rather than per-class: that is, the compiler wouldn't try to instantiate `map::operator[]` unless I made a call to it.
suszterpatt
They're usually instantiated per-method, but you could cause all method to be instantiated using the statement `template std::map<ulint, particle>;`
Joe Gauterin
+1  A: 

The code you posted is perfectly fine and compiles without any errors at the for line in GCC and Comeau (Onlie) compilers. Right now I have no way to try it in VS2008 specifically, unfortunately.

If the error is indeed triggered by the for line, I'd suspect a problem in the compiler. There's a chance that the implementation of std::map<>::begin() or std::map<>::end() somehow depends on std::map<>::operator[]() in VS2008, but that would be rather strange.

AndreyT
I can compile that code on VS2008 without errors
J. Calleja
A: 

Case closed. It turns out that I did in fact make the coding mistake of writing a call to operator[], but it was hundreds of lines further down in the source file from where the error was reported. Apparently VS just pointed me to the first usage of a variable of mapType instead of the actual point where it tried to instantiate the method.

suszterpatt