How to instantiate a template class when constructor takes arguments - c++

I'm trying to create a new object of the class Queue<T>, with the following:
Queue<char[40]> *q = new Queue<char[40]>(100);
Then, I want to use this q on another class constructor:
Interface<char[40]> i(q);
If I just use it, I get an error saying invalid conversion from ‘Queue<char [40]>*’ to ‘int’, which I figure means I'm trying to pass the value of q, which is the pointer to it instead of the actual value. Fine. Then I redefined the Interface<T> constructor to receive a pointer instead of the value itself, so the signature is
Interface(DataStructure<T>& q);
Since Queue extends DataStructure. For some reason, now the instantiation of q fails:
undefined reference to `Queue<char [40]>::Queue(int)
But I am quite sure I have written the constructor method WITH an INT parameter
template<typename T>
Queue<T>::Queue(int size): DataStructure<T>(size) {
std::cout << size << std::endl;
}
Why the hell am I getting this error, then? To play with pointers is just getting a mess and I could not figure out by any means what to do now.

This code Queue<T>::Queue(int size) suggests you put the definition in a source file. If you use templates all your code must be in the header file. (There are other approaches, but this is the easiest).

Related

Initialise unique_ptr inside class

I want to initialise the unique pointer inside class after declaration and I tried few ways but unable to resolve the errors..
template <typename T>
struct Destroy
{
void operator()(T *t) const
{
t->destroy();
}
};
class Test
{
std::unique_ptr<IRuntime, Destroy<IRuntime>> runtime;
public:
Test()
{
/*
the function createIRuntime() return type is *IRuntime.
I tried using following but all the ways I got error:
1. runtime = std::make_unique<IRuntime, Destroy<IRuntime>> (createIRuntime());
2. runtime = createIRuntime();
3. runtime = std::unique_ptr<IRuntime, Destroy<IRuntime>> (createIRuntime());
Works fine if I do follow.
std::unique_ptr<IRuntime, Destroy<IRuntime>> runtime(createIRuntime());
*/
/* how to initialize the unique pointer here*/
}
};
runtime = std::make_unique<IRuntime, Destroy<IRuntime>> (createIRuntime());
Presumably IRuntime is an abstract class, which can't be constructed directly.
But even if it could be constructed as-is, only the 1st template parameter specifies the type to create. The 2nd and subsequent template parameters specify the types of parameters for the constructor that is called.
So, this statement is trying to call an IRuntime constructor that takes a Destroy<IRuntime> object as a parameter, passing a raw IRuntime* pointer to that parameter. No such constructor exists, so this fails to compile.
runtime = createIRuntime();
std::unique_ptr does not have an operator= that takes a raw pointer, only a std::unique_ptr. std::unique_ptr has a constructor that takes a raw pointer, but that constructor is marked explicit. So this fails to compile, too.
runtime = std::unique_ptr<IRuntime, Destroy<IRuntime>> (createIRuntime());
This is correct, and works just fine:
Online Demo
Another statement that works is:
runtime.reset(createIRuntime());
Online Demo
Also, since the code you showed is inside of another constructor, you can (and should) use that constructor's member initialization list:
Test() : runtime(createIRuntime())
{
}
Online Demo

How to fix 'attempting to reference a deleted function' when the compiler implicitly deleted it

I am trying to make a generic class that can represent any object in its most base form, bits. To do this I created a Union of an array of chars (essentially bytes) and the object that the characters make up. Unfortunately when building, I get a strange warning and error for my union.
Warning: "The destructor was implicitly defined as deleted."
Error: "Attempting to reference a deleted function."
(both occur on the line following the definition of my union)
I know that you can create custom destructors for structs, classes and unions, but there is not a need to if you are not freeing up dynamic memory, correct? Yet somehow a destructor I never defined is being automatically called and the compiler deleted it implicitly. Hence the error.
The next thing I attempted was defining a destructor within my union; it did nothing because I never asked the os for additional memory. It was once again deleted. I needed to figure out why the compiler was deleting my function and then causing an error when trying to call it after it deleted it.
I attempted looking for this error in the Microsoft visual studio list, and what it came up with was that not making the constructor public would cause this error. Additionally, looking online here I found that oftentimes the copy constructor is what causes an error because it was never defined. So i tested it by creating a class of my own and using the copy constructor = on it. It worked just fine, but gave me the same error when attempting to use it with my typeAsChar class. Interestingly enough, this error is not called when I use my class with the C default structs, int, double, etc.
Here is the code that causes the issue.
template <class type>
union typeAsChar
{
type obj;
char arr[sizeof(type)];
};
template <class type>
class wontWork
{
public:
wontWork() {/* Do nothing, no data entered */}
wontWork(const type& obj) { foo.obj = obj; }
~wontWork() {/* When this goes out of scope, the default
destructor of the member 'type' should be called */}
typeAsChar<type> foo;
};
int main()
{
double testNum = 12345;
std::string testStr = "Hello World\n";
wontWork<std::string> test1(testStr); // has error
std::cout << test1.foo.obj;
wontWork<double> test2(testNum); // No error
std::cout << test2.foo.obj;
return 0;
}
Oddly enough, this compiles and runs perfectly with wontWork<std::string> commented out, but fails when my class is made with an object of anything other than the standard c structs (int, double, etc). Any clarification on the matter would be much appreciated.
Here is the answer by #Miles Budnek that worked perfectly. Thanks a lot for your info, I never knew that was a functionality in c++.
"reinterpret_cast(&object) is a well-defined way to access the bytes that make up an object (even if it's not very useful for something like std::string). Type-punning via union is not well-defined. – Miles Budnek"

Bizarre error on address of class with templated member

I encountered a weird error when modifying my class structures, which I couldn't reproduce with simpler classes.
Situation:
I have decided to have a class Input have a reference (a plain old pointer) to the object to be manipulated by the user's key input, Camera. Previously I linked them via Input's constructor: Input in(&cam); but after including a templated member in Camera: Buffer<Layout> buffer my whole main function went berserk.
Previously this was fine:
Camera cam();
Input in(&cam);
cam.setProj(glm::mat4(1.0f)); // Example of function call
The headers are of course in separate files, and the implementations in .cpp-files.
Input has a member Camera *cam and the constructor for Input is:
Input::Input(Camera *camera){
this->cam = camera;
}
Problem:
It no longer is fine. The error message is:
Input::Input(Input &&): cannot convert argument 1 from
'Camera(__cdecl *)(void)' to 'Camera *'
Additionally, every attempt to call Camera's functions gives two additional errors: expression must have class type and left of '.func' must have class/struct/union.
Attempt to create a minimal example:
Tl;dr: didn't quite get there. Or at least the issue isn't directly in taking the address of a class with a template member. The following code works.
#include <stdio.h>
#include <stdlib.h>
template <typename T>
class Member{
public:
Member(T variable):var(variable){};
T var;
};
class Owner{
public:
Owner(int m):member(m){};
Member<int> member;
};
class Referencer{
public:
Referencer(Owner *o){this->op = o;};
Owner *op;
};
int main(){
Owner o(1);
Referencer r(&o);
printf("%d\n", r.op->member); // Output is 1.
return 0;
}
As the above example works, I'm not sure whether it actually affects the situation to have a template member. I'm really lost with this one. Any help is greatly appreciated!
Camera cam();
It is a simple function declaration. You declare a function returning Camera and accepting zero arguments. And your MSVC compiler complains about it!
Input::Input(Input &&): cannot convert argument 1 from 'Camera(__cdecl *)(void)' to 'Camera *'
Just use:
Camera cam;
and let the default constructor to be called.

Why uncalled template class members aren't instantiated?

I was wondering that when I create an instance of a class template with specifying the template type parameter.
1) why the non-called function do not get instatiated ? .
2) dont they get compiled until I try to use it ?
3) what is the logic behind this behavior ?
Example
template <class T>
class cat{
public:
T a;
void show(){
cout << a[0];
}
void hello(){
cout << "hello() get called \n";
}
};
int main(){
cat<int> ob1; // I know that show() did not get instatiated, otherwise I will get an error since a is an int
ob1.hello();
}
Templates aren't code - they're a pattern used to make the actual code. The template isn't complete until you supply the parameters so the code can't be made ahead of time. If you don't call a function with a particular set of template parameters, the code never gets generated.
If they instantiated the entire class, then you might get invalid code.
You don't always want that.
Why? Because in C++, it's difficult (and in some cases, outright impossible, as far as I know) to say, "only compile this code if X, Y, and Z are true".
For example, how would you say, "only my copy constructor if the embedded object can be copied"? As far as I know, you can't.
So they just made them not compile unless you actually call them.
To embellish a little more: this is typically called duck typing, and the bottom line is that it allows you to write "class patterns" of which some member functions may apply when instantiated with one template type, other members may apply when instantiated with a second template type, and by only requiring the ones you actually call to compile, you get to write a lot less code for operations that wind up being common ones.
By not requiring all member functions to be compiled you get all the niceties of static type checking on the functions that actually are compiled.
For example, imagine you had:
template <typename E>
class myContainer {
// Imagine that constructors, setup functions, etc. were here
void sort(); // this function might make sense only if E has an operator< defined
E max(); // compute the max element, again only makes sense with a operator<
E getElement(int i); // return the ith element
E transmogrify(); // perhaps this operation only makes sense on vectors
};
Then you have
// sort() and getElement() makes total sense on this, but not transmogrify()
myContainer<int> mci;
// sort and max might not be needed, but getElement() and transmogrify() might
myContainer<vector<double>> mcvd;
No code is generated for cat<int>::show() because you never call it. If you did call it you would get a compilation error. Template functions which are never called do not exist.
Templates are little more than test substitution mechanisms. This makes them very powerful. You, as the programmer, may want to create a cat<int> knowing that you will never call show() or call anything else that would be invalid. The compiler lets you know if you did, so it works out nicely.
So if your question is "why does it work this way", I would ask you "why not"? It's a design choice. This choice allows me to use a template type safely and still benefit from other parts of the code. What's the harm? You also generate less code, which is a good thing, right?

C++ template compilation error - recursive type or function dependency

I wrote a template class which is giving compilation error
template<class T>
class Entity
{
string EntityName;
int EntitySize;
Entity<T*> pPrev;
Entity<T*> pNext;
public:
Entity<T>(const string & name, int size)
{
EntityName = name;
EntitySize = size;
}
//member functions
};
I am using MSVC++ 2008, and the error is :
fatal error C1202: recursive type or
function dependency context too
complex
I have not written any recursive function in my class. Then why this error? Please help.
Alright. I'm explaining you the problem you're facing. But first thing first. You said:
I wrote a template class which is
giving compilation error
First of all, as far as C++ is concerned, there is no such thing as a "template class," there is only a "class template." The way to read that phrase is "a template for a class," as opposed to a "function template," which is "a template for a function." Again: classes do not define templates, templates define classes (and functions).* Quoted from here.
Now, lets see the error:
fatal error C1202: recursive type or
function dependency context too
complex
The error says it all. $14.7.1 from the Standard explains the cause of your problem very well, giving you even an example which is very much close to what you're doing. So I don't even need to write a single word of my own. Here is $14.7.1
4 There is an implementation-defined
quantity that specifies the limit on
the total depth of recursive
instantiations, which
could involve more than one template. The result of an infinite
recursion in instantiation is
undefined. [ Example:
template < class T > class X {
X<T >* p; // OK
X<T*> a; //implicit generation of X<T> requires
//the implicit instantiation of X<T*> which requires
//the implicit instantiation of X<T**> which ...
};
—end example ]
Please read the comment with X<T*> a, which is pretty much the case with you too. So your problem is not because of recursive function, it's rather because of recursive instantiation of class template, causing from these lines:
Entity<T*> pPrev;
Entity<T*> pNext;
Hope, it solves your problem!
EDIT : But I'm wondering what are you trying to achieve with Entity<T*> pPrev? It seems its a typo, and you probably wanted to write Entity<T>* pPrev. Same with pNext. Is that so?
And an advice to improve the design : Use Member Initialization list, instead of Assignment. That is, write your constructor the following way,
Entity<T>(const string & name, int size) : EntityName(name), EntitySize(size)
{
//all assignments moved to initialization list.
}
Read this : Why should I prefer to use member initialization list?
Read the error message more closely. The "too complex" thing is not a recursive function, it's a recursive type or function dependency. The type Entity<T*> depends on the type Entity<T>, recursively. When the compiler tries to generate the code for Entity<int>, it will have to figure out Entity<int*> (in order to implement the pPrev and pNext members), which means it will have to figure out Entity<int**>, etc. - infinitely. That isn't allowed.
But that's just how the compiler knows something is wrong. It doesn't know what is wrong, because it can't think about how to program. (If it could, it would just write your program for you.)
The logical error is that Entity<T*> means "an object which is an Entity with template type pointer-to-T". What you really wanted, in order to make a linked list, is "a pointer to an object which is an Entity with template type T". That is spelled Entity<T>*, with the * outside the angle brackets.
But the real problem is that you are trying to create your own linked list. Don't do that. Use the standard library containers. If you're smart enough to use std::string, you should be smart enough to use the containers (std::vector, std::list, etc. - in a sense, std::string is a container, too, albeit a very special-purpose one) too.
Your template definition is infinitely recursive. You define template class Entity<T> that contains objects of type Entity<T*> as members. Objects Entity<T*> will, according to the same definition, contain objects of type Entity<T**>. The latter will in turn contain objects of type Entity<T***> and so on, as infinitum. In other words, your infinitely recursive template definition makes no sense.
Either terminate the recursion or think about what it is you are really trying to implement. I strongly suspect that your member definitions were supposed to have type Entity<T>*, not Entity<T*>.
Change
Entity<T*> pPrev;
Entity<T*> pNext;
to
Entity<T> *pPrev;
Entity<T> *pNext;
Your type definition is recursive...
You have written a recursive type. Entity has other Entity members. You should change the Entity members into a pointer or reference.