Inheritance and conversion between 2 classes failed c++ - c++

I have class Signal and Image and both classes have method with same name but different input parameters and output parameter. Is is allowed?
template <class T> class Signal {
public:
Signal<T> zeroPadding(Signal<T>);
}
template <class T> class Image:public Signal<T>
{
public:
Image(void);
~Image(void);
Image(int,int);
Image(int,int,double);
Image(int,int,double,double);
Signal<T> zeroPadding(Image<T>);
template <class T> Image<T>::Image(int width,int height):Signal(width,height) {}
template <class T> Image<T>::Image(int width,int height,double dt):Signal(width,height,dt) {}
template <class T> Image<T>::Image(int width,int height,double dt,double t0 ):Signal(width,height,dt,t0) {}
template <class T> Signal<T> Image<T>::zeroPadding(Image<T> im2){
Image<T> i1 =(*this);
Image<T> i2 =im2;
if (i1.getHeight()==i2.getHeight()){
....
return(im2);
}
}
}
int main() {
Image<int> *a=new Image<int>(2,3);
Image<int> *b=new Image<int>(1,3);
(*a).zeroPadding(*b); //when I try to debug it failed with error error LNK2019:
//unresolved external symbol
//"public: __thiscall Signal<int>::~Signal<int>(void)" (??1?$Signal#H##QAE#XZ)
//referenced in function
//"public: __thiscall Image<int>::~Image<int>(void)" (??1?$Image#H##QAE#XZ)
}
Another question: What about if I want to call in main function (*a).Signal::zeroPadding(*b) how I can convert (*a) and (*b) to be Signal?

Because of how the linker works with templates, your implementation should be on the same file as the declaration. You get LNK2019 because the method is only declared but not defined, the compiler doesn't know what to do with it.
Conversion is possible. You need to explicitly cast a pointer to a or b as Signal.

Yes, it is allowed. If member functions are not declared as virtual, then the functions to be called are determined by the caller's class. In your case, The zeroPadding function is being called by Image type which is the derivative class, so the functions in the Image class will overload the base class.
And your error message
unresolved external symbol
public: __thiscall Signal<int>::~Signal<int>(void)" (??1?$Signal#H##QAE#XZ)referenced in function
public: __thiscall Image<int>::~Image<int>(void)" (??1?$Image#H##QAE#XZ)
implies that you have declared the destructor for Signal and Image template class, but didn't implement them, so there will be a link error;
And for your last question, since *a and *b are the derivative class instances of class Signal, so you can convert them to Signal at ease. Every simple methods of type casting will do that.static_cast<Signal<int> >(*a) or directly use (Signal)(*a) is enough.
Update: Seems like that this is a very old but common met issue about seperate compilation. :)
What is seperate compilation? An easy way to explain, if you put your implementation codes in a different source file with the declaration file in writing a template class, then you are using seperate compilation. There is a keyword export specifically for this scenario, but the compiler support isn't that good.
Suggestion is that to put the implementation codes together into the declaration file or maybe include the implementation file into the header file for template class.
Templates and separate compilation
http://www.cs.uofs.edu/~bi/se516/chapter4/tsld022.htm
http://www.cplusplus.com/forum/beginner/73735/

Related

Template ctor mssing

I assume the answer will be simple, but I cannot figure out a solution.
I have a class to be used as an interface in the h-file:
template <typename T>
class MyInterface
{
public:
MyInterface();
};
In the cpp-file it is:
#include "MyInterface.h"
template<typename T>
MyInterface<T>::MyInterface()
{
}
My class using the interface is:
class Test : MyInterface<int>
{
};
When compiling I get the error, the ctor of MyInterace is not declared.
unresolved external symbol "public: __thiscall MyInterface::MyInterface(void)" (??0?$MyInterface#H##QAE#XZ) referenced in function "public: __thiscall Test::Test(void)"
Having the ctor declared in the h-file, it compiles.
Templates are instantiated on the fly. If you want to put the constructor in a cpp file, you must specialize it.
#include "MyInterface.h"
template<>
MyInterface<int>::MyInterface()
{
}
Otherwise, it must be in a header as all template functions are managed inline.
If you'd like to keep code organized, make an inl file, with all the function bodies of your code, and then include it at the bottom of your header.
// MyInterface.h
template <typename T>
class MyInterface
{
public:
MyInterface();
};
#include "MyInterface.inl"
// MyInterface.inl
template<class T>
MyInterface<T>::MyInterface()
{
}

C++ Templated function calling a managed function

I'm trying to build a wrapper around a managed class so I can call it from native code.
Here is the managed function :
void MyManagedFunction(MyStruct iStruct)
{
// Code according to what are the types of the 2 MyStruct members
}
struct MyStruct
{
public MyStruct(Object iValue1, Object iValue2) : this()
{
Value1 = iValue1; // Often contains DateTime::Now
Value2 = iValue2;
}
public Object Value1;
public Object Value2;
}
In my case, Value1 will almost always be System::DateTime::Now and the Value2 will almost always be a common data type (int, double, float, string, bool). I thought of making two templated function in the wrapper.
In the wrapper's .h I have the following :
#ifdef MYWRAPPER_EXPORTS
# define MYWRAPPER __declspec(dllexport)
#else
# define MYWRAPPER __declspec(dllimport)
#endif
class MYWRAPPER MyWrapper
{
public:
MyWrapper();
~MyWrapper();
template <class T> void MyNativeFunction(T iParam1)
{
MyStruct^ wStruct = gcnew MyStruct(System::DateTime::Now, iParam1);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
template <class T, class W> void MyNativeFunction(T iParam1, W iParam2)
{
MyStruct^ wStruct = gcnew MyStruct(iParam1, iParam2);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
};
This wrapper compiled without problem. The problem obviously occurred when I included the .h in the purely native code. Since I can't hide the content of the templated function, I have managed stuff visible on the native side which prevent the native code from compiling.
I was wondering if there was a workaround in order to achieve this. I don't mind if I'm limited into using only primitive types as parameters for the function. The best thing is if I was able to simply hide the content of the templated function in the native code so it only knows about the signature
Here's what I've tried/considered so far :
Converting the parameters to void* and call a function in which would call the managed one. By doing so, I can't cast the void* back to an object since I lose its type and using typeid to get the 'T' or 'W' type doesn't help since it vary from a compiler to another.
Overloading the function for every types I want to use. This is what I'll most likely use if I doesn't find a better solution. The problem is it means alot of overloading (especially for the 2 parameters function considering the number of combination)
If you know all the types your template will take, you can force instantiate it with those variables and thus put the code for the template functions in the source file instead of a header.
You can look at the example provided in Storing C++ template function definitions in a .CPP file
As he says you can do as below (copy-paste alert):
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);

How to do explicit template instantiation correctly?

I'm using templates for implementing the CRTP pattern. With the code below I'm getting linker errors (for all the methods that are defined in the base class CPConnectionBase) like this:
error LNK2001: unresolved external symbol "public: void __thiscall CPConnectionBase::start(void)" (?start#?$CPConnectionBase#VTNCPConnection####QAEXXZ)
I guess the solution here is explicit template instantiation. And indeed I can build my code when I add
#include "TNCPConnection.h"
template class CPConnectionBase<TNCPConnection>;
to the file CPConnectionBase.cpp. This is certainly the wrong place since I don't want to include the header of all possible derived classes into the source of the base class (I might want to use the base class also in another project with other derived classes).
So my goal is to instantiate the template in the source file of the derived class (TNCPConnection.h or TNCPConnection.cpp), but I couldn't find a solution. Adding
template class CPConnectionBase<TNCPConnection>;
to the file TNCPConnection.cpp does not solve my linker problems, and adding
template<> class CPConnectionBase<TNCPConnection>;
to the file TNCPConnection.cpp gives me a compile time error:
error C2908: explicit specialization; 'CPConnectionBase' has already been instantiated
How can I get rid of the linker errors without making the implementation of the base class dependent of the header files of the derived classes?
Here is the skeleton of my code:
CPConnectionBase.h
template <class Derived>
class CPConnectionBase : public boost::enable_shared_from_this<Derived>
{
public:
void start();
};
CPConnectionBase.cpp
#include "stdafx.h"
#include "CPConnectionBase.h"
template<class Derived>
void CPConnectionBase<Derived>::start()
{
...
}
TNCPConnection.h
#include "CPConnectionBase.h"
class TNCPConnection : public CPConnectionBase<TNCPConnection>
{
public:
void foo(void);
};
TNCPConnection.cpp
#include "stdafx.h"
#include "TNCPConnection.h"
void TNCPConnection::foo(void)
{
...
}
The definition of CPConnectionBase::start() must be available at the place where you explicitly instantiate the class - otherwise the function will not be instantiated, and this non-instantiation happens silently (with linker errors following).
The standard solution is a header CPConnectionBase.hpp that defines the template functions declared in CPConnectionBase.h. Include CPConnectionBase.hpp in TNCPConnection.cpp and explicitly instantiate there.
I should add a note here:
MSVC allows to declare the explicit specialization before the member functions, inside the same compilation unit.
GCC (4.7) requires them to be at the end of the file.
I.e.
MSVC:
template class TClass<Base>;
template <class T> void TClass<T>::Function() {}
GCC:
template <class T> void TClass<T>::Function() {}
template class TClass<Base>;
First, I'd suggest renaming CPConnectionBase.cpp to CPConnectionBase.inl, as it doesn't contain any non-template code.
At the point where you instantiate the template, you need to #include <CPConnectionBase.inl> first. I'd suggest doing it in TNCPConnection.cpp.
Alternatively, you can move the CPConnectionBase implementation to the the CPConnectionBase.h header file, and the compiler will handle the instantiation automatically.
move the templated code from the .cpp to the header.
When you include a header with templates, the templated code is genereated in the target code according to what it finds in the header.
If the code is in the .cpp file it can't be found and thus cant be generated (because you only included the .h)
You could also use the "Seperation Model". Just define the template in one file, and mark that
definition with the keyword export:
export template <class Derived>
class CPConnectionBase : public boost::enable_shared_from_this<Derived>
{
public:
void start();
};

Static const member initialization in templated class

I have a problem regarding 'static const' member initialization. In a templated class I define a const member and initialize it outside the class.
When I include the .h file where this class is implemented in multiple .cpp files, I get an LNK2005 error (I'm using VS2010) that says the constant is already defined.
// List.hpp
template <class T>
class List {
static const double TRIM_THRESHOLD;
};
template <class T>
const double List<T>::TRIM_THRESHOLD = 0.8;
I tried putting the member initialization in a .cpp file, but then I get a linker error saying that the constant is not defined at all. If the list is not templated and I put the initialization in a .cpp file, all is fine.
Is there any solution for this situation? I have #ifdef/define clauses around the file already, and it's definitely not a solution.
You should define the constant in a source file not a header (so it only gets defined once) since this is a template which you need to keep in the header(and all instances have the same value) you can use a common base class.
class ListBase {
protected:
ListBase() {} // use only as base
~ListBase() { } // prevent deletion from outside
static const double TRIM_THRESHOLD;
};
template <class T>
class List : ListBase {
};
// in source file
double ListBase::TRIM_THRESHOLD = 0.8;
Another option is to have it as a static function:
static double trim_threashold() { return 0.8; }
Edit: If your compiler supports C++11 you make your static method a constexpr function so that it has all the optimization opportunities that using the value directly has.

Inheriting from a virtual template class in C++

How do I inherit from a virtual template class, in this code:
// test.h
class Base {
public:
virtual std::string Foo() = 0;
virtual std::string Bar() = 0;
};
template <typename T>
class Derived : public Base {
public:
Derived(const T& data) : data_(data) { }
virtual std::string Foo();
virtual std::string Bar();
T data() {
return data_;
}
private:
T data_;
};
typedef Derived<std::string> DStr;
typedef Derived<int> DInt;
// test.cpp
template<typename T>
std::string Derived<T>::Foo() { ... }
template<typename T>
std::string Derived<T>::Bar() { ... }
When I try to use the DStr or DInt, the linker complain that there are unresolved externals, which are Derived<std::string>::Foo() and Derived<std::string>::Bar(), and the same for Derived<int>.
Did I miss something in my code?
EDIT:
Thanks all. It's pretty clear now.
You need to define template<typename T> std::string Derived<T>::Foo() { ... } and template<typename T>
std::string Derived<T>::Bar() { ... } in the header file. When the compiler is compiling test.cpp it doesn't know all the possible values of T that you might use in other parts of the program.
I think there are some compilers that have connections between the compiling and linking steps that notice references to missing template instantiations and go instantiate them from the .cpp file where they are declared. But I don't know which they are, and the functionality is exceedingly rare to find.
If you define them in the header file most compilers will emit them as a 'weak' symbol into every compilation unit in which they're referenced. And the linker will toss out all except for one definition of the weak symbol. This causes extra compilation time.
Alternately, there are syntaxes for explicitly instantiating templates and forcing the compiler to emit definitions right there. But that requires you to be aware of all the values T could possibly have and you will inevitably miss some.
You have to ensure that the member functions are instantiate for all the required types somewhere.
Usually this is accomplished by defining template functions inline in the header file where they are declared so that any use of the functions will cause them to be instantiated.
As an alternative, you can use explicit instantiations in the source file where you define them but this does require you to know in advance all the types that your template will ever be instantiated for.
This doesn't really have much to do with derivation. It's just a general rule with templates: with most compilers (anything but Comeau) you have to put the full implementation of a template where it's visible in every translation unit that will instantiate that template -- normally in the header.
Even with Comeau, you have to use the export keyword to make things work right. Since They're the only ones that implement export, chances are pretty good that you don't care much though.