Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C4251 warning using std::vector<std::string>

2,200 views
Skip to first unread message

Edward Diener

unread,
Aug 1, 2002, 10:37:48 PM8/1/02
to
I have this construct in a DLL ( simplified case of actual problem ) :

#include <vector>
#include <string>

class __declspec(dllexport) SomeClass
{
private:
std::vector<std::string> avar; // Line 7
public:
std::vector<std::string> * ReturnVar() { return(avar); }
};

When I compile I get C4251 warning:

"myheader.h(7) : warning C4251: 'avar' : class 'std::vector<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> > > >' needs to have dll-interface to be used by
clients of class 'SomeClass'"

Huh ! My class is a C++ standard class template instantiation. When it used
it will be instantiated by the user.

Anyway, to satisfy the compiler, in order to export the class I write, in
the same DLL:

template class __declspec(dllexport) std::vector<std::string>;

Is this what is needed ? If so, why ?

Eugene Korobko

unread,
Aug 2, 2002, 3:46:56 AM8/2/02
to
There is a problem with STL and Dll. Try to use dynamic (dll) CRT.

"Edward Diener" <eddi...@tropicsoft.com> wrote in message
news:OD7vo1cOCHA.1976@tkmsftngp11...

Edward Diener

unread,
Aug 2, 2002, 7:36:51 AM8/2/02
to
I am. All of my DLLs use the dynamic RTL.

"Eugene Korobko" <ekor...@yandex.ru> wrote in message
news:efXwMifOCHA.2592@tkmsftngp09...

Craig Powers

unread,
Aug 2, 2002, 9:23:10 AM8/2/02
to
Edward Diener wrote:
>
> I have this construct in a DLL ( simplified case of actual problem ) :
>
> #include <vector>
> #include <string>
>
> class __declspec(dllexport) SomeClass
> {
> private:
> std::vector<std::string> avar; // Line 7
> public:
> std::vector<std::string> * ReturnVar() { return(avar); }
> };
>
> When I compile I get C4251 warning:
>
> "myheader.h(7) : warning C4251 [...]

>
> Huh ! My class is a C++ standard class template instantiation. When it used
> it will be instantiated by the user.

You are correct. In this case, the warning is spurious and may be
ignored or disabled.

> Anyway, to satisfy the compiler, in order to export the class I write, in
> the same DLL:
>
> template class __declspec(dllexport) std::vector<std::string>;
>
> Is this what is needed ? If so, why ?

No, this is not needed, though I don't imagine it would hurt anything
and might even avoid causing each client to generate this instantiation.

I'm not sure the syntax is right, though... I think to export a
template instantiation, you need to use the "extern" keyword.

Sergei

unread,
Aug 2, 2002, 10:38:08 AM8/2/02
to
"Edward Diener" <eddi...@tropicsoft.com> wrote in message news:OD7vo1cOCHA.1976@tkmsftngp11...
> I have this construct in a DLL ( simplified case of actual problem ) :
>
> #include <vector>
> #include <string>
>
> class __declspec(dllexport) SomeClass
> {
> private:
> std::vector<std::string> avar; // Line 7
> public:
> std::vector<std::string> * ReturnVar() { return(avar); }
> };
>
> When I compile I get C4251 warning:
>
> "myheader.h(7) : warning C4251: 'avar' : class 'std::vector<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> > > >' needs to have dll-interface to be used by
> clients of class 'SomeClass'"
>
> Huh ! My class is a C++ standard class template instantiation. When it used
> it will be instantiated by the user.

Exactly. It will be instantiated when compiling every client.
Furthermore inline functions (all functions :) will be expanded
at every call.

> Anyway, to satisfy the compiler, in order to export the class I write, in
> the same DLL:
>
> template class __declspec(dllexport) std::vector<std::string>;
>
> Is this what is needed ? If so, why ?

If you want the only dllexported copy of the functions be
used in every client, you need this before YourHeader.H
in the module you want it be instantiated and dllexported.
You need

template class __declspec(dllimport) std::vector<std::string>;

before YourHeader.H in all other modules to suppress
instantiation. And you need to compile them with Ob0
option to suppress inlining.
Actually no one goes that far and I suspect everyone
has this warning disabled :)

Sergei

Edward Diener

unread,
Aug 2, 2002, 4:05:49 PM8/2/02
to
OK, evidently I don't really need to export the instantiated template, which
is just fine by me.

I say this because in place of std::string I change to a nested class of an
exported class instead, and all efforts to provide an exported template
instantiation of a vector of this nested class leads to failure, so i just
assume the compiler is broke and can't do it:

----------------------------------------------------------------------------
---------------------------------------------------

#include <string>
#include <vector>

#if defined(BUILDING_SOMECLASS)
#define SOMECLASS_IMPORT_EXPORT __declspec(dllexport)
#else
#define SOMECLASS_IMPORT_EXPORT __declspec(dllimport)
#endif

class SOMECLASS_IMPORT_EXPORT SomeClass
{
public:
class MyNestedClass { public: std::string x; int y; bool operator < (const
MyNestedClass & oth) { return(x < oth.x ); } };
private:
std::vector<MyNestedClass> avar;
public:
std::vector<MyNestedClass> * ReturnVar() { return(avar); }
};

template class SOMECLASS_IMPORT_EXPORT
std::vector<SomeClass::MyNestedClass>;

----------------------------------------------------------------------------
---------------------------------------------------

Then with BUILDING_SOMECLASS defined:

C:\PROGRAM Files\Microsoft Visual Studio\VC98\INCLUDE\xutility(50) : error
C2678: binary '<' : no operator defined which takes a left-hand operand of
type 'const struct SomeClass::MyNestedClass' (or there is no acceptable
conversion)
C:\PROGRAM Files\Microsoft Visual Studio\VC98\INCLUDE\vector(218) : see
reference to function template instantiation 'bool __cdecl
std::lexicographical_compare(const struct SomeClass::MyNestedClass *,const
struct SomeClass::MyNestedClass *,const struct SomeClass::MyNestedClass
*,const struct SomeClass::MyNestedClass *)' being compiled

The compiler obviously isn't parsing the nested type correctly.

"Sergei" <ser...@summertime.mtu-net.ru> wrote in message
news:#gHZAJjOCHA.1724@tkmsftngp13...

Doug Harrison [MVP]

unread,
Aug 2, 2002, 4:37:49 PM8/2/02
to
Edward Diener wrote:

See this message:

http://groups.google.com/groups?selm=2h9vrto0kglebcsdg012c1r13jfck1dfdm%404ax.com

--
Doug Harrison
Microsoft MVP - Visual C++
Eluent Software, LLC
http://www.eluent.com
Tools for VC++, VS.NET, and Windows

Sergei

unread,
Aug 3, 2002, 12:56:24 PM8/3/02
to
"Edward Diener" <eddi...@tropicsoft.com> wrote in message news:O1iCQ$lOCHA.388@tkmsftngp09...

This is a whole nother thing. You need a non-member version of the operator:

class MyNestedClass {
friend bool operator < (const MyNestedClass &l, const MyNestedClass &r) {
return l.x < r.x ;


}
public:
std::string x;
int y;

};

Sergei

Sergei

unread,
Aug 5, 2002, 4:02:11 AM8/5/02
to
"Sergei" <ser...@summertime.mtu-net.ru> wrote in message news:OVu936wOCHA.1740@tkmsftngp13...

> "Edward Diener" <eddi...@tropicsoft.com> wrote in message news:O1iCQ$lOCHA.388@tkmsftngp09...
> > OK, evidently I don't really need to export the instantiated template, which
> > is just fine by me.
> >

Well, declaring the member-operator const would suffice:

class MyNestedClass {
public:
std::string x;
int y;

bool operator < (const MyNestedClass & oth) const { return x < oth.x; }
};

Though anyway the non-member version is better.

Sergei

0 new messages