The following works on solaris, but doesn't compile on windows visual studio 6. is there a way to do this differently so it compiles in both places?

In ComandLineArg.h
-------------------------
class CommandLineArg
{
private:
..etc..
static int longestDescr;
..etc..
};

In CommandLineArg.cpp
-------------------------------

CommandLineArg::longestDescr=0;

Error on visual studio:
error C2501: 'longestDescr' : missing storage-class or type specifiers

Dani AI

Generated

A few concise clarifications and portable fixes that tie the thread together.

The static-member error is a linkage/definition issue rather than a runtime one. As noted, the out‑of‑class definition must spell the type — that is a real definition at namespace scope and older compilers that assumed implicit int were nonstandard. One definition (with its type) must appear in exactly one translation unit. Note also that an in‑class initializer is allowed only for static const integral members (and even then an out‑of‑class definition is required if the member is ODR‑used).

The map/insert problem stems from MSVC6’s nonconforming STL and overload-resolution quirks. A portable, VC6‑friendly approach is to avoid the range overload and insert elements explicitly while avoiding unnecessary copies (pass the source map by const reference). Example pattern:

template<class K, class V>
void Properties<K,V>::addMap(const std::map<K,V>& src)
{
    for (typename std::map<K,V>::const_iterator it = src.begin(); it != src.end(); ++it)
        myMap.insert(*it);
}

An alternative (still portable to modern STL but occasionally problematic on VC6) is to use std::copy with std::inserter:

#include <algorithm>
#include <iterator>

std::copy(src.begin(), src.end(), std::inserter(myMap, myMap.end()));

Practical checklist for MSVC6 compatibility: keep template definitions visible to the compiler (header or an included .inl/.hpp), prefer const references over pass‑by‑value for containers, use typename for dependent iterator types, and expect odd STL bugs or missing overloads. As and observed, these issues are compiler/STD‑library artifacts; upgrading to a more modern MSVC (the OP noted VS .NET 2003 worked) removes most of these headaches.

Recommended Answers

All 12 Replies

You forgot the type:

int CommandLineArg::longestDescr=0;

I didn't realize I needed to. Why do I need to specify the datatype? (The syntax looks to me as if it is supposed to return an int rather than that it IS an int..)


(Also, why do I not need to on Solaris Workshop compiler?)

>> Why do I need to specify the datatype?
It's a definition. Any valid definition is also a valid declaration, and standard C++ disallows implicit int declarations.

>> The syntax looks to me as if it is supposed to return an int rather than that it IS an int..
How does an object return anything? It might evaluate to something, but only after its definition during use.

>> Also, why do I not need to on Solaris Workshop compiler?
It's either pre-standard implicit int, where if a type is needed, int is assumed, or it's a compiler extension. I would guess the former.

I added the int on it and it worked both on Sun and Visual Studio. Thanks.


(I now have to try and deal with all of MS VStudio's other really complicated STL related warnings and errors - of course all of the rest of the code works fine on SUN as well...)

Here's another good one for you. This also compiles (and runs fine on Solaris)

Properties.h

template <class K, class V> class Properties : public Printable
{
 ...etc...
 protected:
 
 map<K,V> myMap;
void addMap( map<K,V> mapToAdd);
 
...etc..
};

Properties.hpp

template <class K, class V> void Properties<K,V>::addMap( map<K,V> mapToAdd)
{
 myMap.insert( mapToAdd.begin(), mapToAdd.end() ); 
}

And the wonderfully succint error:
c:\development\danlibs\src\properties.hpp(129) : error C2664: 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<
char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char
>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<
char> > > >::iterator __thiscall std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::bas
ic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::insert(class std::_Tree<class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char
> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struc
t std::char_traits<char>,class std::allocator<char> > >,
class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<cl
ass std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator,const struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,st
ruct std::char_traits<char>,class std::allocator<char> > > &)' : cannot convert parameter 2 from 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,
struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocat
or<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_strin
g<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char
_traits<char>,class std::allocator<char> > > >::iterator' to 'const struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std:
:allocator<char> > > &'
Reason: cannot convert from 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > co
nst ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_trai
ts<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<cha
r> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator' to
'const struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >'
No constructor could take the source type, or constructor overload resolution was ambiguous
c:\program files\microsoft visual studio\vc98\include\xmemory(70) : while compiling class-template member function 'void __thiscall Properties<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std:
:basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::addMap(class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>
,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >
)'

Dave,

(It looks like I have to install perl for this to work, is that correct?)

I was meaning to try to mess with it, but I never got around to it -- but I believe so.

Are you trying to define that function outside of the header? That ussually can cause problems.

Yes, but it's in an .hpp, and all files that require the class include the .hpp file (rather than the .h). in addition, it works perfectly fine on Solaris, only using Visual Studio does it not compile...

I just wrote this up real quick does this compile on your VC++. It works for me on Dev-C++(MinGW(GCC)) :)

#ifndef tester_h
#define tester_h

#include <map>

template<class K, class V> class tester
{
    public:
    std::map<K,V> myMap;
    void addMap(std::map<K,V> mapToAdd);
};

#endif
#ifndef tester_hpp
#define tester_hpp
#include <map>
#include "tester.h"

template<class K, class V> void tester<K,V>::addMap(std::map<K,V> mapToAdd)
{
    myMap.insert( mapToAdd.begin(), mapToAdd.end() ); 
}

#endif

Note that the code I posted before compiles fine in visual studio .net 2003, so it's gotta be something specific with visual studio 6...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.