I have a template class in C++/CLI that looks like this:
template <typename Hdr, typename T>
class DataFile : public DataFileBase
{
protected:
Hdr* header;
Signal <T>* signal;
string fileName;
public:
DataFile ()
: header (0), signal (0), fileName ("") {};
...
// Specialize the ReadSignal function for HP EU Data.
template <>
void ReadSignal <HPDataHeader, float> (ifstream* dataFile)
{
...
}
...
};
This is all defined and implemented in a *.h file and it works fine.
Now I need to use this template class somewhere else that has no need for
the
specialized function but I still have to add a using statement for
HPDataHeader (which
is in a pure native C++ library) because of the specialized type. In other
words, I'm
carrying garbage along when I include the header. So I want to move the
function
specialization out of the *.h file and into a *.cpp file. The code in the
*.cpp file
that I use is like this:
// Specialize the ReadSignal function for HP EU Data.
template <typename Hdr, typename T>
void DataFile <HPDataHeader, float>::ReadSignal (ifstream* dataFile)
{
...
}
This results in a compilation error:
error C2244: 'UERDDataFile::DataFile<Hdr,T>::ReadSignal' : unable to match
function
definition to an existing declaration
and the output is this:
1>------ Build started: Project: DataFile, Configuration: Debug Win32 ------
1>Compiling...
1>DataFile.cpp
1>.\DataFile.cpp(75) : error C2244:
'UERDDataFile::DataFile<Hdr,T>::ReadSignal' :
unable to match function definition to an existing declaration
1> with
1> [
1> Hdr=double,
1> T=float
1> ]
1> definition
1> 'void UERDDataFile::DataFile<Hdr,T>::ReadSignal(std::ifstream *)'
1> with
1> [
1> Hdr=double,
1> T=float
1> ]
1> existing declarations
1> 'void UERDDataFile::DataFile<Hdr,T>::ReadSignal(std::ifstream *)'
1> with
1> [
1> Hdr=double,
1> T=float
1> ]
1>Build log was saved at
"file://c:\UERD\URoot\DataFile\DataFile\Debug\BuildLog.htm"
1>DataFile - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It looks to me like the 'definition' is exactly the same as the 'existing
declarations'! What am I doing wrong????
I also tried:
// Specialize the ReadSignal function for HP EU Data.
template <>
void DataFile <HPDataHeader, float>::ReadSignal (ifstream* dataFile)
{
...
}
which is more in line with examples that I found but that resulted in a slew
of
compilation errors as well as the C2244 error.
TIA, Dick
Ben Voigt [C++ MVP] - 17 Mar 2008 18:03 GMT
> I have a template class in C++/CLI that looks like this:
>
[quoted text clipped - 14 lines]
> template <>
> void ReadSignal <HPDataHeader, float> (ifstream* dataFile)
Do you mean for these types to specialize the containing class? They don't.
> {
> ...
> }
>
> ...
> };
Maybe what you want is more like:
template <typename Hdr, typename T, typename CompileTimeOverrides =
DataFile<Hdr,T> >
class DataFile : public DataFileBase
{
protected:
Hdr* header;
Signal <T>* signal;
string fileName;
public:
DataFile ()
: header (0), signal (0), fileName ("") {};
void ReadSignal( ifstream* dataFile ) {
static_cast<CompileTimeOverrides*>(this)->ReadSignalImpl(); }
void ReadSignalImpl(ifstream* dataFile) { ... }
};
/* in the file defining HPDataHeader */
struct HPDataHeader { ... };
class HpEuDataFile : public DataFile<HPDataHeader, float, HpEuDataFile>
{
protected:
/* re-implement constructors, yuck! */
public:
void ReadSignalImpl(ifstream* dataFile) { ... }
};
template<>
class DataFile<HPDataHeader, float> : public HpEuDataFile
{
/* re-implement constructors, yuck! */
};
As a result of the need to re-implement constructors, you may want to apply
PImpl, move most of the constructor logic to a protected helper, or some
other mechanism.