473,386 Members | 2,042 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Make templated member function instantiate object of given class type

93 64KB
Say I have two classes A and B. I want A to have a templated function "makeObject()", which makes a new object of the given class template-type and stores it internally.

Is the below correct?
Expand|Select|Wrap|Line Numbers
  1. A a;
  2. a.createObject<B>();
Classes + Functions:
Expand|Select|Wrap|Line Numbers
  1. class A
  2. {
  3.     template<typename Tclass>
  4.     unsigned int createObject();
  5. }
  6.  
  7. template<typename Tclass>
  8. unsigned int A::createObject()
  9. {
  10.     Tclass var = new Tclass();
  11.     return 0;
  12. }
  13.  
  14. class B {};
Aug 2 '18 #1

✓ answered by Xillez

OK, I got it running by doing the first point in this thread: https://stackoverflow.com/a/10632266

I moved the function implementation into the header.

Thanks btw weaknessforcats :-)

13 2603
weaknessforcats
9,208 Expert Mod 8TB
I fixed your code. Compare what I did to the original code.


Don't forget to make your member functions public when calling them from outside the class definition.




Expand|Select|Wrap|Line Numbers
  1. class A
  2. {
  3. public:
  4.     template<class Tclass>
  5.     Tclass* createObject();
  6. };
  7.  
  8. template<class Tclass>
  9. Tclass* A::createObject()
  10. {
  11.     return new Tclass();
  12. }
  13.  
  14. class B {};
  15.  
  16. int main()
  17. {  
  18.     A a;
  19.     B* ptr =  a.createObject<B>();
  20. }
Aug 2 '18 #2
Xillez
93 64KB
Not exactly, but I appreciate the effort :-)

I think you missed the part with "stores it internally". The thing is that the new object should not be sent out, but stored inside.

A thing I forgot to mention: the return of the createObject function is the id (or game-id) of the new object (so returning 0 inside is fine).

The main difference is that the template class is used as the return type of the function in you're code, but not in my code.
Aug 2 '18 #3
weaknessforcats
9,208 Expert Mod 8TB
The createObject member function would want to store the created object as a private member variable inside its class. That would mean a member variable of type T. That would mean a template class.

One way around that is to use polymorphism on the created objects so the class only needs to store a base class pointer.

If this doesn't work you can design a bag and keep the bag in the class object and use a bag handler to move created objects in and out.

You might look at Microsoft and the VARIANT. Lots of typecasting required but easy to use.
Aug 4 '18 #4
Xillez
93 64KB
Sorry for late reply.

I tried implementing one of you're solutions, but still have the same problem.

Error:
CMakeFiles/Framework.dir/source/src/main.cpp.o: In function `main':
main.cpp:(.text+0x33): undefined reference to `void A::createEntity<E>()'

Could it be that when the functions are generated at compile-time, it doesn't know about class B yet (aka hasn't beed defined), then once I try to link to the function, it simply doesn't exists? But this would contradict that in my "A.hpp" file, I include "B.hpp", so how can it not be defined?

Expand|Select|Wrap|Line Numbers
  1.     class A
  2.     {
  3.         B* obj;
  4.     public:
  5.         template<class Tclass>
  6.         void createObject();
  7.     };
  8.  
  9.     template<class Tclass>
  10.     void A::createObject()
  11.     {
  12.         if (std::is_base_of<B, Tclass>::value) // Does given class extend B?
  13.             obj = new Tclass();
  14.     }
  15.  
  16.     class B {};
  17.  
  18.     class E : plublic B {};
  19.  
  20.     int main()
  21.     {  
  22.         A a;
  23.         a.createObject<E>();
  24.     }
Aug 11 '18 #5
weaknessforcats
9,208 Expert Mod 8TB
Your code compiles after I added a forward reference for class B and corrected a misspelling of public in class E:



Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5.  
  6. class B;  //forward reference
  7.  
  8. class A
  9. {
  10.     B* obj;
  11. public:
  12.     template<class Tclass>
  13.     void createObject();
  14. };
  15.  
  16. template<class Tclass>
  17. void A::createObject()
  18. {
  19.     if (std::is_base_of<B, Tclass>::value) // Does given class extend B?
  20.         obj = new Tclass();
  21. }
  22.  
  23. class B {};
  24.  
  25. class E : public B {};
  26.  
  27. int main()
  28. {
  29.     A a;
  30.     a.createObject<E>();
  31. }

The forward reference tells the compiler that there is a class B so don't get all excited. This is sufficient to declare a pointer to B but anything else will require the compiler see the full class definition beforehand.

In this case, class A stores a B*. If B is the base class of a polymorphic hierarchy, the createObject can create a derived class object and store the pointer to it as a base class pointer.

If class A needs to store any old type, then this code won't work.
Aug 11 '18 #6
Xillez
93 64KB
What compiler are you using? I use cmake (default setup with Ubuntu 17.10)

See if you can compile my project?
Aug 11 '18 #7
weaknessforcats
9,208 Expert Mod 8TB
I am using Windows 10 and Visual Studio 2013.

Send me your code and I'll compile it. I prefer one file ending with main().
Aug 11 '18 #8
Xillez
93 64KB
I've managed to compile it in a single file (in zip), using the g++ compiler. It seems to be cmake's compiler...

The file is simplified and built by exchanging includes, with file content with a little cleanup
Aug 11 '18 #9
Xillez
93 64KB
In fact the file attached compiles even with cmake, so it's a problem with multiple files then. Any clue on how I can compile it with multiple files?
Aug 11 '18 #10
weaknessforcats
9,208 Expert Mod 8TB
The code compiles and links for me.


The idea behind multiple files is that each file is compiled separately and then the .obj's are linked by the linker to provide your final executable.


All you need do really is compile each of your source files to get the .obj and then in the linkage section of your make you need to specify which obj's to link.


Compiling with multiple files does not use the #include directive of the preprocessor. The #include combines various source files into a thing called a translation unit and it is this engorged file that is sent to the compiler. This allows you do reuse source code in multiple files without needing multiple copies of the source files.

Which area concerns you? Multiple files merged together into one file or multiple objct files merged together into one executable by the linker?
Aug 11 '18 #11
Xillez
93 64KB
Not really concerned, but it seems as if multiple linked files is the problem. Not really sure why it should be a problem at all though.

As I build the program the cmake compiler tells me what it finished and how many percent is compiled so far, and the Entity class is built before EntityMgr class (so it's available). The EntityMgr.cpp gets it's Entity type from the EntityMgr.hpp file. The main.cpp file knows about it from EntityMgr.hpp.

Console output:
"Scanning dependencies of target Framework
[ 25%] Building CXX object CMakeFiles/Framework.dir/source/ecs/entity/Entity.cpp.o
[ 50%] Building CXX object CMakeFiles/Framework.dir/source/ecs/system/EntityMgr.cpp.o
[ 75%] Building CXX object CMakeFiles/Framework.dir/source/src/main.cpp.o
[100%] Linking CXX executable bin/Framework
CMakeFiles/Framework.dir/source/src/main.cpp.o: In function `main':
main.cpp:(.text+0x33): undefined reference to `unsigned int EntityMgr::createEntity<Entity>()'
collect2: error: ld returned 1 exit status
CMakeFiles/Framework.dir/build.make:146: recipe for target 'bin/Framework' failed
..."

I also tried forward declaration in main.cpp of both EntityMgr and Entity and of Entity in EntityMgr.cpp.
Aug 12 '18 #12
Xillez
93 64KB
OK, I got it running by doing the first point in this thread: https://stackoverflow.com/a/10632266

I moved the function implementation into the header.

Thanks btw weaknessforcats :-)
Aug 12 '18 #13
weaknessforcats
9,208 Expert Mod 8TB
Be careful when you say you moved the function implementation to the header.

You moved a template. A template is used to create a function implementation. It is not the function implantation.

I get excited about this because a header file cannot contain anything that generates machine instructions or allocates memory. All that has to be done in a .cpp file.

So the function implementation goes in a .cpp file and the function prototype goes in the header. The linker will attach the one compiled function to all the places that called it.

You include the header in all the other files.

I hope I haven't confused you. I apologize if I have.
Aug 14 '18 #14

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: lovecreatesbeauty | last post by:
--------- quotation --------- The default method of initialization using special member functions is to perform a bit-for-bit copy from the initializer into the object to be initialized. This...
5
by: Mahesh Devjibhai Dhola | last post by:
Hi All, I want to make a custom class in c#, which extends System.Xml.XmlNode class of BCL. Now in custom class, I have implement abstract methods of XmlNode class also. Now when I am trying to...
2
by: tony | last post by:
Hello! I'm trying to build a class library which has a class called AvestaPlantFunc. In this project building a class libray exist a class called AvestaPlantFunc. In this class is there a...
1
by: Leslaw Bieniasz | last post by:
Hello, I have the following problem: file a.h --------------- template <class T> class A { // some stuff
13
by: docschnipp | last post by:
Hi, I have a bunch of object derived from the same base class. They all share the same constructor with some parameters. Now, instead of using a large switch() statement where I call every...
1
by: david | last post by:
template< typename T > void f( T & t ) { t.g<int>(); } MSVC 2005 compiles this without problems (yes, even when it's instantiated). g++ gives errors. Comeau compiles in "relaxed" mode, but...
3
by: sarbhatt | last post by:
I have a question, in multilevel inheritance: Class Base { }; Class derv1:public Base { }
11
by: Gabriel de Dietrich | last post by:
Hi all! Just out of curiosity: Is there any way to get the address of a particular virtual member function given an object? Some code to make things more clear... class A { public: A() { }
5
by: Alavi | last post by:
Hi Friends, I'm a new comer to the C# and oop world. I have a little problem about the class properties please kindly help me. I have a class named "User" in namespace_A . (User is not a static...
2
by: kino | last post by:
Hello, I am getting the following error 25 C:\Dev-Cpp\main.cpp request for member `no' in `one', which is of non-class type `box' in the code while (!myfile.eof()) {
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.