C++ Virtual Template METHOD | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 1

C++ Virtual Template METHOD

I am stucked in a situation where a class needs to get some parameters that are templates, but this class is NOT a template class, and is a base class that can (must) be derived. The issue I am facing is that C++ does not allow virtual template methods. The Material class CANNOT be a template class : only its method. The Material::send method MUST contains the template parameter. The Material class is a base class that is derived (by PhongMaterial) and only the derived class are used. Another class, Actor, uses the Material as a protected member, and needs to call this template function. The Material method is called, and not the PhongMaterial. How can I get around this issue ? Here's a MCE : https://www.sololearn.com/compiler-playground/c8SlPrm4zJoR

19th Mar 2023, 1:38 PM
NoxFly
NoxFly - avatar
5 Answers
+ 3
I would like to help. But from your example, I do not understand how templates come into play. Also, why these constraints? Why can Material not be template, and why does send need a template parameter? There may be an entirely different solution to your problem, but without understanding the requirements and constraints, I am afraid there isn't much I can do.
19th Mar 2023, 5:19 PM
Ani Jona 🕊
Ani Jona 🕊 - avatar
+ 1
It certainly gives more background. I understand that the entire project is too large, but one must consider shortcomings in the architecture of the project, which I cannot do, but might help to solve the problem. For example, when you write "The material can (or cannot) handles lights, shadows, etc", I ask myself if you have a proper seperation of concerns in your design. Also, I am still not clear what the template parameter T would hold in your code example, and if it is necessary to know the specific information it will have. If not, dependency injection might be an idea to think about, or the template method design pattern, which would result in a loss of type information, I think. But you could implement the send method with template parameters in Material and delegate execution to pure virtual functions by means of the any type. But you lose the type information this way. I hope this helps for now. If you have questions or want to add something, please feel free to do so.
22nd Mar 2023, 8:36 AM
Ani Jona 🕊
Ani Jona 🕊 - avatar
0
This is part of a huge OpenGL environment, and some things must be used "as simple as it is", like Material : in all this huge environment, it is useless to make the entire class a template, so it will be easier to use from an external user of this library. However, Material::send sends some variables it has on the shader it has (with uniforms). The sent variables depends of the material, and cannot be predict apart from itself. The material can (or cannot) handles lights, shadows, etc... and then needs the informations about the scene, which is the class Scene<D>, where D is the dimension of the Scene : either 2D or 3D. For example, a BasicMaterial will only send the matrices MVP, while the PhongMaterial will send the matrices + some other parameters, including parameters that depends of the scene. Maybe another material will send things that depends to the scene, but not the sames. The material stay the same, no matter if the scene is 2D or 3D. If you are a user who use this library, you'll probably want to create a shape, like a cube, using the material of your choice. You'll surely be tired to always write "PhongMaterial<3D> myMaterial;" instead of just "PhongMaterial myMaterial" over the time, while you KNOW your scene is 3D (or 2D). It's why I try to avoid changing Material to a template class. Hope that long explanation can help you to understand the whole thing.
21st Mar 2023, 10:10 PM
NoxFly
NoxFly - avatar
0
you can probably use "std::any" ( a concrete type that can store any type internally . by using type erasure on the arguments, and at the same time allows for type-safe retrieval of the data ). in your case : class Material { public: virtual void send(std::any) { // TODO } }; https://en.cppreference.com/w/cpp/utility/any
22nd Mar 2023, 12:11 PM
MO ELomari
0
Maybe, but I'm not sure using std::any is the most appropriate thing for a language that has strong typing ? But if I'm still blocked it will maybe be the best solution...
22nd Mar 2023, 4:25 PM
NoxFly
NoxFly - avatar