C++ std::vector with pointers to a template class - c++

In a project I am working on I am tying to make a vector with pointers to a template class.
template <typename T>
std::vector<templateClass<T>*> vec;
However, this gives me two errors:
Error C2133: vec : unknown size
Error C2998: std::vector<templateClass<T>*> vec : cannot be a template definition
If I change the code to:
std::vector<templateClass<int>*> vec;
It works fine, so I guess the problem isn't that you cant use template classes with vectors, but that you need to tell the compiler what type to use. Is there any way around this?

When you create a class instance you have to choose the type. In the definition you can write T but at the moment of create instance you have to specify the type.
So if you want define and not creating an instance use typedef.

You can't have a templated member.
The template must come from the class or function templated declaration.
template <typename T>
class blah {
std::vector<templateClass<T>*> vec;
}
The compiler needs the templated typename to be defined somewhere in the code, for example: blah<int>
If you'd have a templated member, you couldn't define the type anywhere in the code, and the compiler wouldn't be able to decide the member's type.
The templated typename is decided when you first use the function or class (either explicitly or implicitly) so you'd have to have the template definition and implementation somewhere that is accessible by the calling code.

It looks like you are trying to define a new type vec<T> as a shortcut to the longer templetized expression. Normally, this would be done with a typedef, however C++ does not support templetized typedefs.
Note, that in the current code you are essentially trying to define a variable called vec, but you are not giving it a specific type for T and that's why the compiler is complaining.

Currently C++ doesn’t support template typedefs so you have to use the most common solution, proposed by Herb Sutter (http://gotw.ca/gotw/079.htm)

Related

(Can I minimize the) Footprint of template in my C++ Code?

I have a large class which basically handles one buffer of variable (numeric) datatype. So it seems a good choice to use a class template with this datatype as the only parameter. I'm not experienced in C++ and I wonder/worry a bit about the "footprint" such a template makes in my code.
There are three implications of templates which in my (C++ unexperienced) eyes are not necessary and make code ugly. I tried to avoid them, but neither did I find a good example how to do it nor did I manage to find it out by myself.
So the goal of this question is: Can you either confirm the following statements or give a counterexample?
When using a class template, all class methods have to go into the header file. Even if they have no templated type in their interface or implementation.
When using a static method or member of the class, I always have to specify a template parameter (MyClass< double > :: MY_STATIC), even if the templatization does not affect any of the static properties of the class.
When using the class as a parameter for a function, I always have to give a template parameter, even when this function does not access any of the templated members? (function myFunc(MyClass< double> & myClass){ do something } )
As a general rule, don't have functions/data members in a template class which does not use the template parameters. Have a base class, put all non-template related things there, your template class should derive from it.
To answer your questions:
yes, everywhere where you need to instantiate the template, you need to see the full definition of the class and it's functions
yep, but put that into the base class
yes, see above
EDIT: One of the reasons to move to base class is code bloating (this expression actually exist, you can google it for more info): If you don't move the template unrelated code to a base class, the very same template independent code will be copied for all instantiation of your template, which means a lot of unnecessary code. If you put it to a base class, you will only have this code once.
Yes. On the plus side, the code is only generated when the metod is actually used for the specialization.
Yes. However, there is no (other then design choice) need for a static method to be a memeber of the templated class if it has no use for the templated parameter.
Yes. The size and memory layout of the structure is determined by the template parameter.

C++ template explicit specialization - calling existing member function

I'm using explicit template specialization to initialize a std::vector with information but only for a specific type of std::vector, thus the explicit specialization. Within the constructor, if I try to call push_back or any other existing function in std::vector, compilation fails. What is the problem and how do I fix it?
simplified example:
namespace std
{
template<>
class vector<int>
{
public:
vector(void)
{
int value = 5;
push_back(value);
}
};
}
compiler message:
In constructor 'std::vector<int>::vector()':
error: 'push_back' was not declared in this scope
push_back(value);
^
Explicit specializations are completely different classes that are separate from the primary template. You have to rewrite everything.
In normal situations where you control the primary template, you would typically have some sort of common base class or base class template to collect common structures.
With a given library, it is generally a very bad idea to add specializations (unless the library explicitly says it's OK). With the C++ standard library, this is outright undefined behaviour.
(The main problem is that other translation units may be using the template instantiation which you're specializing without seeing your specialization, which violates the one-definition rule.)
Template specializations are unrelated types from both the primary template and any other specialization. It is unclear what you are attempting to do, as it is also illegal to provide specializations of templates in the std namespace unless the specialization uses your own user defined type.
If you can explain the problem to solve, you might get other options, like specializing a member function rather than the template itself...

Must an unused function in a template class be valid?

In a template I have some functions which are only valid for certain template types. GCC seems to be happy with this, but I'm not sure it is valid. Unlike typical SFINAE the function itself is not a template.
template<typename T>
struct generic {
T item;
void get_limited() {
item.limited();
}
};
Provided I don't call get_limited, is it okay to instantiate this class with a type that does not implement limited?
If no, how can I solve this? I have a generic container class where certain features are enabled based on the allocate it is storing (so not directly on the type as above, but still a template parameter).
Template functions are instantiated on demand, so if there is no use of the function it need not be correct, at least for some possible instantiations. The standard does state that if a template is not valid for any instantiating type, the program is ill-formed (although the compiler is not required to diagnose it) even if it is never instantiated.
This feature is used in the standard library in different parts, where the requirements of a single function might be stricter than the general requirements that the template places on the instantiating types. For example, in the case of std::map, in general, the value type does not need to be default constructible, but if you want to use operator[] then it needs to be, since that operator might need to create an empty element if the key is not present.

turning a non-template class into a template

I have a self made data structure (for example linked list) that works well, but when I made the class I did it based around strings, but now I want to take that data structure, and use it to hold another self made data type. I know that this involves templates (the ability to take a working data structure and apply any data type to it), but I have not really worked with them.
what steps should I follow to turn a non-template class into a template class?
The main thing you need to do is put the template specification in front:
template <class T>
class A {
...
};
Then use T instead of using your string type.
There are lots of other things to consider when creating templates, but it depends on the particular situation.
You will specify your new type when you use the template:
A<MyType> my_object;
that is basic actions
Move all method definitions of your class from .cpp to .h file
Put template specifications (template <class T>) before all declarations and definitions
Change all class name specifiers to template names, i.e. A::A(){} should became A<T>::A(){}
If it required, change the names of method calls to ones with type parameters
Change all entries of the previous type to the type parameter name
can be a lot of the other things of course.

Forward Declaration of a Base Class

I'm trying to create proper header files which don't include too many other files to keep them clean and to speed up compile time.
I encountered two problems while doing this:
Forward declaration on base classes doesn't work.
class B;
class A : public B
{
// ...
}
Forward declaration on STD classes doesn't work.
namespace std
{
class string;
}
class A
{
string aStringToTest;
}
How do I solve these problems?
The first problem you can't solve.
The second problem is not anything to do with standard library classes. It's because you declare an instance of the class as a member of your own class.
Both problems are due to the requirement that the compiler must be able to find out the total size of a class from its definition.
However, the compiler can work out the size of a pointer to a class, even if it doesn't yet have the full definition of it. So a possible solution in such cases is to have a pointer (or reference) member in the consuming class.
Not much help in the base class case, because you won't get an 'is a' relationship.
Nor is it worth doing for something like std::string. Firstly, it's supposed to be a convenient wrapper around a character buffer, to save you from doing memory management on something so simple. If you then hold a pointer to it, just to avoid including the header, you're probably taking a good idea too far.
Secondly (as pointed out in a comment), std::string is a typedef to std::basic_string<char>. So you need to forward declare (and then use) that instead, by which time things are getting very obscure and hard to read, which is another kind of cost. Is it really worth it?
As answered before by Earwicker, you can not use forward declarations in any of those cases as the compiler needs to know the size of the class.
You can only use a forward declaration in a set of operations:
declaring functions that take the forward declared class as parameters or returns it
declaring member pointers or references to the forward declared class
declaring static variables of the forward declared type in the class definition
You cannot use it to
declare a member attribute of the given type (compiler requires size)
define or create an object of the type or delete it
call any static or member method of the class or access any member or static attribute
(did I forget any?)
Take into account that declaring an auto_ptr is not the same as declaring a raw pointer, since the auto_ptr instantiation will try to delete the pointer when it goes out of scope and deleting requires the complete declaration of the type. If you use an auto_ptr in to hold a forward declared type you will have to provide a destructor (even if empty) and define it after the full class declaration has been seen.
There are also some other subtleties. When you forward declare a class, you are telling the compiler that it will be a class. This means that it cannot be an enum or a typedef into another type. That is the problem you are getting when you try to forward declare std::string, as it is a typedef of a specific instantiation of a template:
typedef basic_string<char> string; // aproximate
To forward declare string you would need to forward declare the basic_string template and then create the typedef. The problem is that the standard does not state the number of parameters that basic_string template takes, it just states that if it takes more than one parameter, there rest of the parameters must have a default type so that the expression above compiles. This means that there is no standard way for forward declaring the template.
If, on the other hand you want to forward declare a non-standard template (non STL, that is) you can do it for as long as you do know the number of parameters:
template <typename T, typename U> class Test; // correct
//template <typename T> class Test; // incorrect even if U has a default type
template <typename T, typename U = int> class Test {
// ...
};
At the end, the advice that was given to you by Roddy: forward declare as much as you can, but assume that some things must be included.
In both cases the compiler needs to know the size of the type. Therefore, a forward declaration will not suffice. A base class could add members or require a virtual table. The string member would require the size of the class to be increase to store the size of the STL string class.
Forward declaring STL classes is often inadvisable since the implementations commonly include explicit template instantiations that speed up compilation.
You're trying too hard to solve something that isn't actually a problem. Use the header files you need, and reduce - WHERE POSSIBLE - the requirement for them. But don't try and take it to extremes because you'll fail.
In some cases, the PIMPL idiom may help you, but not here.
For your base classes, you need to have the full type definition, not just a declaration. Derived type headers will need to #include the header for their base classes.
For classes in the std namespace, you must include the proper header - <string> in this case - and then do one of 3 things:
Fully qualify the type: std::string
aStringToTest
Put a using declaration for just
that type: using std::string;
Put in a using declaration for the
std namespace: using namespace std;
> Seems that forward declaration is useless for base classes and stl classes.
Correction...
Forward declaration is INAPPROPRIATE for base classes and object member. (It's not "useless", it is "inapplicable".)
A base class MUST be declared (not forward declared) when being declared as a based class of another class.
An object member MUST be declared (not forward declared) when being declared by another class, or as parameter, or as a return value. NOTE: by-reference or by-pointer does not have that constraint.
Correction...
Forward declaration of STL classes is -- as per ISO 14882 -- undefined behavior.
http://www.gotw.ca/gotw/034.htm