C++ only implementation of template class - c++

I do not have access to c++11 for this project.
I have a C++ class; lets call it Bar, it looks something like this:
Header FooBar.h:
#include "Fancy.h" // <--- Dependency
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>
{
};
}
Cpp:
None
Fancy is a lib that is being statically linked into a dll. The problem is that when other projects want to use the dll they include "FooBar.h" it says that it cannot find "Fancy.h"
Basically I want projects that include the dll to be able to use this class without needing any additional libraries or headers.
My solution was to just put it in a cpp and have no header file. Unfortintly nothing can find it then? I have tried creating a blank header file that did not work either.
I tried to forward declare it in the header but to do that I need the .h to understand what FancyClass is. I have also tried
namespace Fancy
{
class FancyClass;
class ALLOCATER;
}
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>;
}
in the header. But that causes many errors.

Short answer, you must include the header in your executable file in order to use the provided library.
Long(er) answer, the compiler needs to know the structure of the class defined in the library.
Imagine that there is a class called MyAwesomeClass that is part of a library you want to use in your executable. The compiler doesn't know anything about that class when you say MyAwesomeClass awesome;. How big is it? What methods can you call on it? Does it inherit from anything?
This information is contained in the header file where the class is declared.
class MyAwesomeClass
{
private:
std::string _name;
public:
MyAwesomeClass();
MyAwesomeClass(const std::string& name);
void print_name();
};
The implementation is defined in the DLL or static library, but when using the type MyAwesomeClass, the compiler needs to know at least its structure. Without including the header, the compiler will complain that it doesn't know what type MyAwesomeClass is (ie. undefined class errors).

Related

Should I include everything I need in a template class header file?

I run into a dilemma when I am writing a generic toString-like template class, which gives a QString representative of common data structures that I use. I wish I can include minimal numbers of other header files in this header file (#include in .h or .c / .cpp?), but also wish to have it not rely on the order it is included (Header file order).
The basic code is like this:
// Some headers
template <typename T>
class PMsg
{
// Public routines
public:
static QString fromType();
static QString fromValue(T const &val);
}; // PMsg
// Inline definition of all methods in PMsg<T>::fromValue
// Some specialisation
// To be continued...
And here comes the problems: container classes. Should I do the following to pulling all container headers to make it work:
// To the beginning
#include <QtCore/QList>
#include <QtCore/QVector>
// After PMsg<T>
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
Or to use macros to detect what headers are included as:
#if defined(QLIST_H)
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
#endif
#if defined(QVECTOR_H)
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
#endif
I might eventually include more than 20 different headers (including some non-Qt classes like those in Eigen), or I might rely on something Qt can change without telling downstream developers and ask my colleagues to include Qt headers before this header for sure.
I am also not sure how much effect on compiling time both ways would cause at this time (which probably should not be considered if I haven't get to this problem).
Is there any other better way to solve this or which way should I follow?
Sorry for the bad question title and thank you for your help.
Based on your description, you are providing a component with a customization point (PMsg<T>) to be used for components being added. It seems that you also want to have a certain set of already known components to take advantage of this customization. This leads to the following reasoning:
To use your component it is necessary to include a specific header (you didn't name it so I'll use "pmsg.h").
Newly created components can, and probably should, provide the relevant customization in their respective header, i.e., there is no need to customize these components in "pmsg.h".
Existing components (e.g. QVector<T>) are not aware of this customization and to seamlessly integrate with your component their customization needs to be declared in "pmsg.h". Without declaring the customization in "pmsg.h" all users would need to remember to also include the header declaring the customization in addition to the header of the existing component. Assuming there is a default implementation for the customization, that would not just have unexpected results but can easily lead to ODR violations when different translations units are inconsistent with respect to the headers they include.
For non-template components you can forward declare the component in "pmsg.h" to declare the customization and then implement it without any includes in the source file implementing the declarations from "pmsg.h". That is, for non-template components being customized there is no need to include the respective header with the declarations, a declaration suffices.
In general you can't safely forward-declare a class template (primarily because default arguments can only be declared for the first declaration). In addition, you'll probably need to provide a definition for the templated customization in the header "pmsg.h". That is, you'll need to include the declarations of all template classes you want/need to customize in your "pmsg.h".
tl;dr: if you want to provide customization for existing components you'll need to declare them in your header and to do so you'll need include their respective declarations, too.

DLL-Exporting static members of template base class

Within a DLL I have an exported non-template class with a template base class. This template base class has a static member variable. I use the static base member in an executable that links to the DLL with the exported non-template class.
In many scenarios I get unresolved external symbols or complaints about inconsistent linkage. I have found one scenario that works, but it seems to be kludgey so I'm wondering if there is a better way and if that better way might also point to deficiencies in VS2010 SP1's C++ compiler/linker.
This is the minimal scenario of the DLL that I could distill - I don't think I could remove anything here without breaking the scenario.
// Header file
template<typename T>
class _MYDLL_EXPORTS TBaseClass
{
public:
static const double g_initial_value;
};
class _MYDLL_EXPORTS MyClass : public TBaseClass<MyClass>
{
};
// Kludge: use this code only when building the DLL, not when including
// from the DLL's client
#ifdef _MYDLL
template<typename T>
const double TBaseClass<T>::g_initial_value = 1e-5;
#endif
// CPP file
#include "header.h"
// Explicit instantiation of the template for the correct parameter.
template class TBaseClass<MyClass>;
Then the user of the DLL
#include <header.h>
#include <iostream>
int main(void) {
MyClass c;
std::cout << c.g_initial_value;
return 0;
}
In C++ generally, when a plain class has a static member, it should be declared in the header, but instantiated in a source file. To do otherwise would cause too many instances of the static class member to be created.
Templates are kind of the same way, except the compiler has some magic for templates that it doesn't have for non-templates. Specifically, it magically eliminates duplicate instances of a template instantiation during the linking phase of a build.
This is the source of your problem: The stuff inside the _MYDLL portion is automatically instantiated by every source file that includes this template and also makes TBaseClass objects. Then the linker automatically eliminates duplicates.
Trouble is, you have two links: the DLL link and the client link. Both will make TBaseClass instantiations, and both will make those g_initial_value objects.
To solve this: Move the stuff in the _MYDLL conditional into the CPP file, so the client won't get instructions to build the instance itself.
The fact that you are using your template class from both the DLL and the EXE make things more confusing, but still, it can work.
First of all, you should implement your template base class entirely in the header file. If you don't know why, then make sure you read the accepted answer to this question.
Now let's forget about templates and DLLs, and consider a much simpler case. Let's say you have class C, with a static member. You would normally code this class in this way:
// C.h file
class C {
public:
static const double g_initial_value;
};
// C.cpp file
const double C::g_initial_value = 1e-5;
Nothing odd or complicated here. Now consider what would happen if you move the static declaration to the header file. If there is only one source file that includes the header, then everything will work just fine. But if two or more source files included this header, then this static member will be defined multiple times, and the linker will not like that.
The same concept applies to a template class. Your #ifdef _MYDLL hack only works because from the DLL you are including this header file only once. But the moment you include this file from another source file you'll start getting linker errors on the DLL! So I completely agree with you, this is not a good solution.
I think one thing that complicates your setup is that you allow both the DLL and the EXE to instantiate this template base class. I think you would have a much cleaner solution if you find an "owner" for each instantiation of the template class. Following your code example, let's replace MyClass with MyDLLClass and MyEXEClass. Then you could make this work like this:
// dll.h
template<typename T>
class _MYDLL_EXPORTS TBaseClass
{
public:
static const double g_initial_value;
};
class _MYDLL_EXPORTS MyDLLClass : public TBaseClass<MyDLLClass>
{
};
// dll.cpp
#include "dll.h"
// this file "owns" MyDLLClass so the static is defined here
template<> const double TBaseClass<MyDLLClass>::g_initial_value = 1e-5;
// exe.h
#include "dll.h"
class MyEXEClass : public TBaseClass<MyEXEClass>
{
};
// exe.cpp
#include "exe.h"
#include <iostream>
// this file "owns" MyEXEClass so the static is defined here
template<> const double TBaseClass<MyEXEClass>::g_initial_value = 1e-5;
int main(int argc, char* argv[])
{
MyDLLClass dll;
MyEXEClass exe;
std::cout << dll.g_initial_value;
std::cout << exe.g_initial_value;
}
I hope this makes sense.
In fact, the exported class's base class is exported too if the base class is a template class, but not true on the contrary. Please refer to http://www.codesynthesis.com/~boris/blog/2010/01/18/dll-export-cxx-templates/
For your specific question, I suggest you define a static method in the base template which returns a variable(pointer?) of interest. Then only one definition will happen across multiple dlls or exe which depends on your library.
While I would suggest using your current approach, actually it's possible to avoid #ifdef by using older syntax for exporting templates from a DLL. All this goes to the DLL's header file:
#pragma once
#ifdef _MYDLL
#define _MYDLL_EXPORTS __declspec(dllexport)
#else
#define _MYDLL_EXPORTS __declspec(dllimport)
#endif
template<typename T>
class _MYDLL_EXPORTS TBaseClass // _MYDLL_EXPORTS is not needed here
{
public:
static double g_initial_value;
};
template<typename T>
double TBaseClass<T>::g_initial_value = 1e-5;
class MyClass;
template class _MYDLL_EXPORTS TBaseClass<MyClass>;
class _MYDLL_EXPORTS MyClass : public TBaseClass<MyClass>
{
};
At runtime the address of g_initial_value in the client code lies within DLL's address space so it seems to work correctly.

Cross source file template instantiation and use

I have a class with several template member functions that I would like to distribute among several source files to speed up compilation times. (The templates are implementation details and are not intended to be used outside the class, hence their definition in sources not headers.)
How would I go about splitting up these templates in such a way that I will not get linker errors? If I have source file A using a template defined in source file B, how do I make sure the appropriate instance of the template is constructed by the compiler?
I could not answer it better than C++ FAQ:
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
Simply don't declare those template items as part of the class in the header file. Then, define your templates only in the source file. For example:
MyClass.hpp
class MyClass
{
public:
void SomePublicMethod() const;
};
MyClass.cpp
template<class T>
void SomethingWithT(T myVal)
{
// ...
}
void MyClass::SomePublicMethod() const
{
SomethingWithT(42);
}

Is it possible to add an object of a class in the class header?

I was wondering if there is a way to put objects of a class in a header?
For example:
class MyClass {
} object;
If I made an object there and then include the header in more than one source file, I get an error of multiply defined symbols found. I am new so don't understand fully everything.
Also, I want to do something like object.function() inside of a different function which is a member of a different class how can I do that?
Assuming you want a single object, in the header file just declare the object:
extern blabla object;
and then in one source file define it:
blabla object;
As for calling a method on an object from a different class, that is perfectly fine as long as the method is public.
class foo
{
public:
void public_method();
private:
void private_method();
};
void some_other_class::method(foo &f)
{
f.public_method(); // this is fine
f.private_method(); // this is not okay, private_method can only be called from
// within foo
}
There's also a third visibility (protected), which comes into play once you start dealing with inheritance.
You can find ways to do it (see the other answers), but just don't do it. As you said, you are new to C++, so better learn the good practices, and when you need global objects - create them in the source (cpp) file.
Besides it, try to avoid using global objects at all, and define your objects inside the classes or functions.
It's not a good practice to put definitions in header files as this would result to the error you encountered. Although there are ways to get around this (extern, header guard), it should be avoided as much as possible. Just remember, put declarations in header files, definitions in source files.
About your second question note you can also call a static method using the :: operator and the class name (without an instance) :
void AnOtherClass::method()
{
TheFirstClass::static_method();
}
You could also make a use of the singleton pattern, if that fits your need in this case.
For your second question. You can always make a class object as a (private) member variable of the class you want to call object.function() from.
For example:
// File a.h, includeguards etc. left out for clarity
class A {
public:
void func();
};
// File b.h
#include "a.h"
class B {
public:
void func();
private:
A object;
};
// File b.c
#include "b.h"
void B::func()
{
object.func();
}
Hope that helps.

Templated superclass linking problem

I'm trying to create a C++ class, with a templated superclass. The idea being, I can easily create lots of similar subclasses from a number of superclasses which have similar characteristics.
I have distilled the problematic code as follows:
template_test.h:
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a);
virtual int Foo();
};
class Base
{
protected:
Base(int a);
public:
virtual int Foo() = 0;
protected:
int b;
};
template_test.cpp:
#include "template_test.h"
Base::Base(int a)
: b(a+1)
{
}
template<class BaseClass>
Templated<BaseClass>::Templated(int a)
: BaseClass(a)
{
}
template<class BaseClass>
int Templated<BaseClass>::Foo()
{
return this->b;
}
main.cpp:
#include "template_test.h"
int main()
{
Templated<Base> test(1);
return test.Foo();
}
When I build the code, I get linker errors, saying that the symbols Templated<Base>::Templated(int) and Templated<Base>::Foo() cannot be found.
A quick Google suggests that adding the following to main.cpp will solve the problem:
template<> Templated<Base>::Templated(int a);
template<> int Templated<Base>::Foo();
But this does not solve the problem. Adding the lines to main.cpp does not work either. (Though, interestingly, adding them to both gives 'multiply defined symbol' errors from the linker, so they must be doing something...)
However, putting all the code in one source file does solve the problem. While this would be ok for the noddy example above, the real application I'm looking at would become unmanageable very fast if I was forced to put the whole lot in one cpp file.
Does anyone know if what I'm doing is even possible? (How) can I solve my linker errors?
I would assume that I could make all the methods in class Templated inline and this would work, but this doesn't seem ideal either.
With templated classes, the definitions must be available for each translation unit that uses it. The definitions can go in a separate file, usually with .inl or .tcc extension; the header file #includes that file at the bottom. Thus, even though it's in a separate file, it's still #included for each translation unit; it cannot be standalone.
So, for your example, rename template_test.cpp to template_test.inl (or template_test.tcc, or whatever), then have #include "template_test.inl" (or whatever) at the bottom of template_test.h, just before the #endif of the include guard.
Hope this helps!
The problem is that when your Templated file is compiled, the compiler doesn't know what types it will need to generate code for, so it doesn't.
Then when you link, main.cpp says it needs those functions, but they were never compiled into object files, so the linker can't find them.
The other answers show ways to solve this problem in a portable way, in essence putting the definitions of the templated member functions in a place that is visible from where you instantiate instances of that class -- either through explicit instantiation, or putting the implementations in a file that is #included from main.cpp.
You may also want to read your compiler's documentation to see how they recommends setting things up. I know the IBM XLC compiler has some different settings and options for how to set these up.
The C++ FAQ-lite covers this, and a couple of ways round it.
You don't have to make all the methods "inline", but you should define the method bodies in template_test.h, rather in template_test.cpp.
Some compilers can handle this split, but you have to remember that at one level, templates are like macros. for the compiler to generate the a template for your particular , it needs to have the template source handy.
When the compiler is compiling main.cpp, it sees the class definition has member function declarations, but no member function defintions. It just assumes that there must be a definition of "Templated" constructor and Foo implementation somewhere, so it defers to the linker to find it at link time.
The solution to your problem is to put the implementation of Templated into template.h.
eg
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a) : BaseClass(a) {}
virtual int Foo() { return BaseClass::b; }
};
Interestingly, I could get your code to link by putting this at the end of template_test.cpp.
void Nobody_Ever_Calls_This()
{
Templated<Base> dummy(1);
}
Now the compiler can find an instance of Templated to link with. I wouldn't recommend this as a technique. Some other file might want to create a
Templated<Widget>
and then you'd have to add another explicit instantiation to template_test.cpp.