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

Separate Template Definition I wrote class Data in header. The C++ Compiler compiled without errors. I decided to move all member functions into source code because they are for implementation. I do not like that they are placed in class body.

7 views
Skip to first unread message

Immortal Nephi

unread,
Jul 29, 2010, 12:39:21 PM7/29/10
to
I wrote class Data in header. The C++ Compiler compiled without
errors. I decided to move all member functions into source code
because they are for implementation. I do not like that they are
placed in class body.

I got error message:

Linking...
Main.obj : error LNK2001: unresolved external symbol "public:
__thiscall Data<unsigned char>::operator unsigned char(void)" (??B?
$Data@E@@QAEEXZ)
C:\Main.exe : fatal error LNK1120: 1 unresolved externals

Could be problem with member function cast operator. All other
member functions complied without any problems.

// Data.h
#if !defined(DATA_H )
#define DATA_H

template< typename T >
class Data {
public:
Data();
~Data();

operator unsigned char ();

private:
unsigned char x;
};

#endif // end macro !defined( DATA_H )

// Data.cpp

template< typename T >
Data< T >::Data() : x( 5 ) {}

template
Data< unsigned char >::Data();


template< typename T >
Data< T >::~Data() {}

template
Data< unsigned char >::~Data();


// Error unresolved linkage
template< typename T >
Data< T >::operator unsigned char () {
return x;
}

template
Data< unsigned char >::operator unsigned char ();

// main.cpp

int main() {
Data< unsigned char> data;
unsigned char x = data;

return 0;
}

Jonathan Lee

unread,
Jul 29, 2010, 1:31:06 PM7/29/10
to
On Jul 29, 12:39 pm, Immortal Nephi <Immortal_Ne...@hotmail.com>
wrote:

>         I wrote class Data in header.  The C++ Compiler compiled without
> errors.  I decided to move all member functions into source code
> because they are for implementation.  I do not like that they are
> placed in class body.
>
>         I got error message:
>
> Linking...
> Main.obj : error LNK2001: unresolved external symbol "public:
> __thiscall Data<unsigned char>::operator unsigned char(void)" (??B?
> $Data@E@@QAEEXZ)
> C:\Main.exe : fatal error LNK1120: 1 unresolved externals
>
>         Could be problem with member function cast operator.  All other
> member functions complied without any problems.

GCC compiled this without a complaint, so it's legal-ish (?).
BUT you have 3 specializations declared in data.cpp without
definitions. Maybe MS is expecting the definitions.

(I actually have no idea if this is legal or not since I've
never declared a specialization and not immediately implemented
it).

--Jonathan

Immortal Nephi

unread,
Jul 29, 2010, 1:38:36 PM7/29/10
to

Yes, I use Microsoft Visual C++ Compiler 9.0. Does anyone experience
that way?
Each member function can have more than one specification such as
char, short, long, enum, etc. I put 15 enum specifications in EACH
member functions on source code. Microsoft Visual C++ Compiler
compiled successfully without any problems, but only one problem is
the cast operator member function.

Jonathan Lee

unread,
Jul 29, 2010, 1:46:14 PM7/29/10
to
On Jul 29, 1:38 pm, Immortal Nephi <Immortal_Ne...@hotmail.com> wrote:
> Each member function can have more than one specification such as
> char, short, long, enum, etc.

Of course, but do you actually have code that goes with these
specifications? Because the linker error is saying that MSVC
cannot find the code that goes with the function you declared.
I suspect that GCC simply falls back to the template code for
operator char(), but MS is hung up on it.

In other words, try getting rid of this line in data.cpp

template
Data< unsigned char >::operator unsigned char ();

*OR* implement it

template<>
Data<unsigned char>::operator unsigned char() {
return x;
}

[Of course, that doesn't explain why the constructor and
destructor are found... ]

> I put 15 enum specifications in EACH
> member functions on source code.

I don't know what this means, but I also can't see how it
is relevant. Except that, you know, it sounds like what
you posted isn't actually the code you're having problems
with.

--Jonathan

Paul Bibbings

unread,
Jul 29, 2010, 1:54:14 PM7/29/10
to
Immortal Nephi <Immorta...@hotmail.com> writes:

Taking your code as is (adding only the relevant includes to Main.cpp
and Data.cpp), I can confirm the link failure with VC++ 2008 Express:

d:\CPPProjects\CLCPP>cl /EHsc Main.cpp Data.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01
for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

Main.cpp
Data.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:Main.exe
Main.obj
Data.obj
Main.obj : error LNK2019: unresolved external symbol "public:


__thiscall Data<unsigned char>::operator unsigned char(void)"

(??B?$Data@E@@QAEEXZ) referenced in function _main


Main.exe : fatal error LNK1120: 1 unresolved externals

d:\CPPProjects\CLCPP>

However, the same code seems to compile fine using gcc-4.4.3:

18:48:03 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $i686-pc-cygwin-g++-4.4.3 -static
Main.cpp Data.cpp

18:48:49 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $

so, there appears to be some difference of opinion between the two
compilers as to whether your code should work or not.

Regards

Paul Bibbings

Paul Bibbings

unread,
Jul 29, 2010, 2:06:07 PM7/29/10
to
Jonathan Lee <jonathan...@gmail.com> writes:

Is this right, what you are proposing here? If you look back at the OP's
code, what he provided were not specializations at all, but rather
*explicit instantiations*, including:

template< typename T > // primary template
Data< T >::operator unsigned char() {
return x;
}

template // explicit inst. for uchar
Data< unsigned char >::operator unsigned char();

I'm not that up to speed on this because I have never found myself using
explicit instantiations. Still, it is not my /expectation/ that any
further `implementation' is required here. The OP's code is, surely,
merely saying "I have this template. I shall be needing to use it on
Data< unsigned char>. Instantiate the relevant member functions (ctor,
dtor, op uchar) for me." Of course, this is necessary here, owing to the
fact that the primary definitions are themselves present in a source,
rather than a header, file. Beyond that, I'm not immediately seeing
that there is any problem with this.

Regards

Paul Bibbings

Immortal Nephi

unread,
Jul 29, 2010, 2:26:19 PM7/29/10
to
On Jul 29, 1:06 pm, Paul Bibbings <paul.bibbi...@gmail.com> wrote:

Do Google and look for Q239436. It answers your question why Visual C+
+ 2008 fails to link template member function.

Jonathan Lee

unread,
Jul 29, 2010, 2:31:17 PM7/29/10
to
On Jul 29, 2:06 pm, Paul Bibbings <paul.bibbi...@gmail.com> wrote:
> Is this right, what you are proposing here?  If you look back at the OP's
> code, what he provided were not specializations at all, but rather
> *explicit instantiations*, including:

Ahh.. that clears things up. I didn't realize you could do that
per member function. I thought it was only for entire classes,
as in

template class Data<unsigned char>;

In that case, ignore everything I said. You're absolutely right.

--Jonathan

Paul Bibbings

unread,
Jul 29, 2010, 2:39:58 PM7/29/10
to

Is this right, what you are proposing here? If you look back at the


OP's
code, what he provided were not specializations at all, but rather
*explicit instantiations*, including:

template< typename T > // primary template


Data< T >::operator unsigned char() {
return x;
}

template // explicit inst. for uchar
Data< unsigned char >::operator unsigned char();

I'm not that up to speed on this because I have never found myself
using
explicit instantiations. Still, it is not my /expectation/ that any
further `implementation' is required here. The OP's code is, surely,
merely saying "I have this template. I shall be needing to use it on
Data< unsigned char>. Instantiate the relevant member functions (ctor,
dtor, op uchar) for me." Of course, this is necessary here, owing to
the
fact that the primary definitions are themselves present in a source,
rather than a header, file. Beyond that, I'm not immediately seeing
that there is any problem with this.

Regards

Paul Bibbings

Paul Bibbings

unread,
Jul 29, 2010, 2:54:30 PM7/29/10
to
On Jul 29, 7:39 pm, Paul Bibbings <paul.bibbi...@gmail.com> wrote:

Apologies for the double post on this.

Regards

Paul Bibbings

Paul Bibbings

unread,
Jul 29, 2010, 3:13:40 PM7/29/10
to

I think that there is a problem with VC over this. If you compile
only your
single file Data.cpp and then run objdump -t Data.obj, you will see
that
there is no symbol for the explicitly instantiated conversion operator
in
the table. On the other hand, even though we already have the
evidence
that it has no problem with explicit instantiations for the ctor and
dtor,
add a member function:

// Data.h


template< typename T >
class Data {
public:

// ...
unsigned char get() const;
};

// Data.cpp
template< typename T >

unsigned char Data<T>::get() const {
return x;
}

template
unsigned char Data< unsigned char >::get() const;

then compile to Data.obj again. Run objdump -t Data.obj *now and
you'll
see that Data< unsigned char >::get() is in the symbol table.

From this, it seems that VS is just not happy with honouring your
request
for an explicit instantiation of your op uchar. That's all that I
can
suggest.

Regards

Paul Bibbings

Immortal Nephi

unread,
Jul 29, 2010, 3:50:07 PM7/29/10
to

You can add many member functions in source code you like.

>    // Data.cpp
>    template< typename T >
>    unsigned char Data<T>::get() const {
>       return x;
>    }


Don't add that line below.

>    template
>    unsigned char Data< unsigned char >::get() const;

I successfully resolved linkage failure. I fixed template class
specification in source code. Cast operator function is working
perfectly.

Add line below.

template
class Data< unsigned char >;

...Before...add many member functions.

Review my code again.

// Data.h
#if !defined(DATA_H )
#define DATA_H

template< typename T >
class Data {
public:

Data();
~Data();

operator unsigned char ();

private:
unsigned char x;
};


#endif // end macro !defined( DATA_H )

// Data.cpp

class Data< unsigned char >;

template< typename T >
Data< T >::Data() : x( 5 ) {}

template< typename T >
Data< T >::~Data() {}

template< typename T >


Data< T >::operator unsigned char () {
return x;
}


// main.cpp

int main() {
Data< unsigned char> data;
unsigned char x = data;

return 0;
}

MS Visual C++ Compiler compiled successfully without errors.

Paul Bibbings

unread,
Jul 30, 2010, 7:54:19 AM7/30/10
to

I have tried this using VC++ 2008 (with cl /EHsc Main.cpp Data.cpp)
and it
doesn't work. I get, as I would expect:

d:\CPPProjects\CLCPP>cl /EHsc Main.cpp Data.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version
15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

Main.cpp
Data.cpp
Data.cpp(5) : error C2906: 'Data<unsigned char>' : explicit
specialization requires 'template <>'

If I change the first code line of your Data.cpp to:

template // explicit instantiation
class Data< unsigned char >;

then VC++ is apparently happy with it. (The omission of `template'
may
have been an oversight on your part when you posted your code.)

However, I am not sure that this *should* work. To me, the explicit
instantiation is then the wrong side of the template definitions, and
certainly gcc-4.4.3 fails your code, thus corrected, with an undefined
reference on *all* of the member functions of your Data class. If,
then,
you move the explicit instantiation to the *end* of your Data.cpp,
after
the definitions, then it works for both gcc and VC.

However, this does not alter the fact that your first attempt -
providing an explicit instantiation for each of the members
individually -
should have been accepted by VC also. In effect, all that you are
doing
here with your second attempt is doing in one line what you had
previously
requested be done in 3. I am beginning to think that there is a bug
here
in VC.

Regards

Paul Bibbings

0 new messages