After reading many posts about similar topics, and thinking about it for a while, still I do not understand why it is forbidden to implement template virtual functions.
The way I see it, this case has nothing to do with mixing static polymorphism with the dynamic one, but it is rather using template differentiation of the functions at the compile-time and then using dynamic polymorphism for each individual created function at the run-time.
Consider this piece of code:
class parrent{
public:
virtual float function(float value)const{
return value;
}
virtual double function(double value)const{
return value;
}
virtual long double function(long double value)const{
return value;
}
virtual ~parrent() = default;
};
class a_child:public parrent{
public:
float function(float value)const override{
return value + 1.5;
}
double function(double value)const override{
return value + 1.5;
}
long double function(long double value)const override{
return value + 1.5;
}
};
Obviously this code is OK and will achieve the expected result.
But using template to rewrite a similar code:
class parrent{
public:
template<typename t__>
virtual t__ function(t__ value)const{
return value;
}
virtual ~parrent() = default;
};
class a_child:public parrent{
public:
template<typename t__>
t__ function(t__ value)const override{
return value + 1.5;
}
};
Is not allowed.
I am not a compiler designer but from what I have read compilers will create a look up table from virtual functions and use them to launch the appropriate function at the run time, which is different from what they do in case of template functions. For any sets of template parameters given to use a template function at the compile time, compiler will create a unique function.
For this example compiler could detect template parameters in compile time simply by looking at how this virtual template function have been used throughout the entire program. Please consider the main function now:
int main() {
parrent* a;
parrent* b;
a = new parrent;
b = new a_child;
std::cout<< a->function(1.6f) << std::endl;
std::cout<< a->function(1.6) << std::endl;
std::cout<< a->function(1.6L) << std::endl;
std::cout<< b->function(1.6f) << std::endl;
std::cout<< b->function(1.6) << std::endl;
std::cout<< b->function(1.6L) << std::endl;
delete a;
delete b;
return 0;
}
Here Compiler will see that the function was used once for a float value, once for a double value and once for a long double value, so in any case it can easily create the right function with appropriate template parameters.
And in the end there will be 3 individual virtual functionS, not just one virtual function.
If we have a function which template parameters could not be deduced from the functions inputs like
template<typename t__>
virtual t__ function(int value){return value;}
Then users can just give the parameters themselves like:
object_pointer->function<double>(1234);
These practices are just what is already being used in case of any template functions, so why would it be different for virtual functions!
the only caveat to this practice that I can think of would be when the template virtual function get instantiated from a child object and never from the parent object or pointer.
Well even in that case same practice could be applied in order to create different virtual functions. Alternatively due to the lack of use of their virtuality they can become normal individual functions.
From the answer and comments it appears that there might be a serious problem with this approach which is obvious to every one else, so please be patient and help me understand it too.
I guess the mentioned problem in answers has something to do with compiler and/or linker not being able to know how many (and what type of) vtables it should produce for a class with regard to the rest of the codes or different translation units that it might face.
Well lets say it can produce an unfinished vtables list and extend it as it go along. The problem of ending up with two vtables or two different instances of a same class in the of case dynamic linking can already happen with instantiation of a template class with a virtual (non template)function.
So it seems that compilers already have a method to circumvent that problem!
First lets not forget that with regards to c, methods or class non static functions are nothing more than simple functions which require an object as one of their parameters, so lets not think of class as some intricate piece of code.
Second let's not get carried away by how compilers and linkers and what not works today. The language should be standard not the way compilers produce executable! Lets not forget that there are still many features in standard c++ 17 that even GCC does not cover yet!
Please explain to me in term of logic not the way compilers and/or linkers work what is the problem?
The way compilers implement polymorphic classes is as follows: the compiler looks at the class definition, determines how many vtable entries are needed, and statically assigns one entry in that vtable to each of the class's virtual methods. Wherever one of those virtual methods is called, the compiler generates code that retrieves the vptr from the class and looks up the entry at the statically assigned offset in order to determine the address that needs to be called.
We can now see how having a virtual template would cause issues. Suppose you had a class containing a virtual template. Now, after the end of the class definition, the compiler doesn't know how large to make the vtable. It has to wait until the end of the translation unit, to see the full list of the specializations of the template that are actually called (or to which a pointer-to-member is taken). If the class is only defined in this single translation unit, this problem could be solved by assigning vtable offsets to the template specializations in some increasing order in which they are encountered, then emitting the vtable at the end. However, if the class has external linkage, this breaks down, as when compiling different translation units, the compiler has no way of avoiding conflicts in the assignment of offsets to specializations of the virtual method template. Instead, the vtable offsets would have to be replaced with symbols that would be resolved by the linker once it has seen the list of referenced specializations from all translation units and merged them into a single list. It seems that if standard C++ required virtual templates to be supported, every implementation would have to require the linker to implement this functionality. I can guess that this will not be feasible any time soon.
I am not a compiler designer but I see a problem with what you are hoping to do.
When you have a virtual template member function, such as
template<typename t__>
virtual t__ function(t__ value)const{
return value;
}
there is no end to the types for which that is applicable. How does the compiler know whether to stop at int and double? There are unlimited number of types for which that function can be instantiated. Would you expect the compiler to generate vtable that takes into account all possible ways that function can be instantiated? That's infinite. It's not doable.
Related
The related procedure code is provided below.I often see such kind of code in open source projects which can run both on Linux and Windows. Somebody told me that it is to avoid compiling warning. Is it really the case?
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info)
{
(void)pub;
(void)info;
}
};
I wonder why not define it like this:
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info){};
};
or
class Base
{
public:
virtual void on_publication_matched(Publisher* pub, PublicationMatchedStatus& info) = 0;
};
Let have a look at the first two examples. They define a function that simply does nothing. The difference lies in the void cast
(void)pub;
(void)info;
which is typically used to avoid the unused-variable warnings by the compiler. It does a cast to void. The expression is discarded afterwards, so effectively e.g. (void)pub does nothing but the compiler won't complain about an unused variable. Since c++17 you can use the maybe unused attribute:
virtual void on_publication_matched([[maybe unused]]Publisher* pub,
[[maybe unused]]PublicationMatchedStatus& info){}
Alternatively, you can also write:
virtual void on_publication_matched(Publisher*,PublicationMatchedStatus&){}
This would also not give a warning. However, I prefer to have descriptive argument names. As remarked by #JaMiT you can use inline comments to get:
virtual void on_publication_matched(Publisher*/*pub*/,
PublicationMatchedStatus& /*info*/){}
Your last example marks the function as purely virtual which is far different from the first to examples. That is you can't create an instance of the pure virtual class. You need to provide an implementation in the derived class to create an instance of it. See also this answer.
This is to avoid unused variable warnings. The statement (void)pub; is a noop (does nothing), yet it still references the variable. Hence, the compiler does not complain that pub is not used.
Other examples do not avoid unused variable warnings and making the member function abstract might not be even desirable or the initial intention.
Problem
I would like to detect if a class has member variables and fail a static assert if they do. Something like:
struct b {
int a;
}
static_assert(!has_member_variables<b>, "Class should not contain members"). // Error.
struct c {
virtual void a() {}
void other() {}
}
static_assert(!has_member_variables<c>, "Class should not contain members"). // Fine.
struct d : c {
}
static_assert(!has_member_variables<d>, "Class should not contain members"). // Fine.
struct e : b {
}
static_assert(!has_member_variables<e>, "Class should not contain members"). // Error.
struct f : c {
char z;
}
static_assert(!has_member_variables<f>, "Class should not contain members"). // Error.
Is there a way to achieve this with SFINAE template? This class may have inheritance or even multiple inheritance with virtual functions (no members in the base classes though).
Motivation
I have a pretty simple setup as follows:
class iFuncRtn {
virtual Status runFunc(Data &data) = 0;
};
template <TRoutine, TSpecialDataType>
class FuncRoutineDataHelper : public iFuncRtn {
Status runFunc(Data &data) {
static_assert(!has_member_variables<TRoutine>, "Routines shouldnt have data members!");
// Prepare special data for routine
TSpecialDataType sData(data);
runFuncImpl(sData);
}
class SpecificRtn :
public FuncRoutineDataHelper<SpecificRtn, MySpecialData> {
virtual Status runFuncImpl(MySpecialData &sData) {
// Calculate based on input
sData.setValue(someCalculation);
}
};
The FunctionalityRoutines are managed and run on a per tick basis. They are customized and can perform a wide variety of tasks such as contacting other devices etc. The data that is passed in can be manipulated by the routine and is guaranteed to be passed in on each tick execution until the functionality is finished. The right type of data is passed in based on the DataHelper class. I wan't to discourage future people from mistakenly adding data to the functionality routines as it is very unlikely to do what they expect. To force this, I was hoping to find a way with static assert.
You can solve this by depending on the compiler doing empty base class optimizations, by checking if a class derived from your T has the same size as an empty class with virtual functions:
template<typename T, typename... BaseClasses>
class IsEmpty
{
// sanity check; see the updated demo below
static_assert(IsDerivedFrom<T, BaseClasses...>::value);
struct NonDerived : BaseClasses... { virtual ~NonDerived() = default; };
struct Derived : T { virtual ~Derived() = default; };
public:
inline static constexpr bool value = (sizeof(NonDerived) == sizeof(Derived));
};
This should work with both single and multiple inheritance. However, when using multiple inheritance, it's necessary to list all base classes, like that:
static_assert(IsEmpty<Derived, Base1, Base2, Base3>::value);
Obviously, this solution rules out final classes.
Here's the updated demo.
Here's the original demo. (doesn't work with multiple inheritance)
You will have to mark the classes in some way or another. Pick a way you are comfortable with, a property or some kind of type integer member with an enum. Whoever makes sub-classes will have to follow your convention to make it work.
All other answers here will be some variant of this.
Any answer that uses a sizeof could not guarantee this will work between platforms, compilers, or even classes on the same platform and compiler, due to easily being able to fit a new member inside the default class member alignment, where the sizes of sizeof could easily end up the same for a sub-class.
Background:
As stated in your code and question, all of that is just plain and basic C ad C++ code, and is resolved entirely at compile time. The compiler will tell you if a member exists or not. After its compiled it's a mash of efficient, nameless, machine code with no hints or help for that kind of thing by itself.
Any name you use for a function or data member effectively disappears, as you know it and see it there, after compile and there is no way to lookup any member by name. Each data member is known only by its numerical offset from the top of the class or struct.
Systems like .Net, Java, and others are designed for reflection, which is the ability to remember class members by name, where you can find them at runtime when you program is running.
Templates in C++, unless mixed mode C++ on something like .Net, are also all resolved at compile time, and the names will also all be gone, so the templates by themselves buy you nothing.
Languages like Objective-C also are written to not fail necessarily if certain types of special members are missing, similar to what you are asking, but under the covers its using a lot of supporting code and runtime management to keep track independently, where the actual function itself and its code are still unware and rely on other code to tell them if a member exists or to not fail on null member.
In pure C or C++ you will need to just make your own system, and be literal about tracking dynamically what does what. You could make enums, or lists or dictionaries of name strings. This is what is normally done, you just have to leave hints for yourself. A class cannot be compiled in a way that gives implicit visibility to future sub-classes by definition, without using some form if RTTI.
Its common to put a type member on a class for this very reason, which could be a simple enum. I would not count on sizes or anything that might be platform dependent.
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?
As I understand it, the compiler can inline a virtual function call when it knows at compile time what the type of the object will be at runtime (C++ faq).
What happens, however, when one is implementing a pure virtual method from a base class? Do the same rules apply? Will the following function call be inlined?
class base
{
public:
virtual void print() = 0;
virtual void callPrint()
{
print(); // will this be inline?
}
};
class child : public base
{
public:
void print() { cout << "hello\n"; }
};
int main()
{
child c;
c.callPrint();
return 0;
}
EDIT:
I think my original example code was actually a poor representation of what I wanted to ask. I've updated the code, but the question remains the same.
The compiler is never required to inline a function call. In this case, it is permitted to inline the function call, because it knows the concrete type of c (since it is not indirected through a pointer or reference, the compiler can see where it was allocated as a child). As such, the compiler knows which implementation of print() is used, and can choose not to perform vtable indirection, and further choose to inline the implementation of the function.
However, the compiler is also free to not inline it; it might insert a direct call to child::print(), or indirect through the vtable, if it decides to do so.
These optimizations in general boil down to the 'as-if' rule - the compiler must behave as-if it was doing a full vtable indirect - this means that the result must be the same, but the compiler can choose a different method of achieving the result if the result is the same. This includes inlining, etc.
The answer is of course "it depends", but in principle there's no obstruction to optimization. In fact, you're not even doing anything polymorphic here, so this is really straight-forward.
The question would be more interesting if you had code like this:
child c;
base & b = c;
b.print();
The point is that the compiler knows at this point what the ultimate target of the dynamic dispatch will be (namly child::print()), so this is eligible for optimization. (There are two separate opportunities for optimization, of course: one by avoiding the dynamic dispatch, and one coming from having the function body of the target visible in the TU.)
There are only a couple of rules you should be aware of:
1) The compiler is never forced to inline - even using the directive or defining a method in the header.
2) Polymorphism MUST ALWAYS WORK. This means that the compiler will prefer calling the function via the vftable rather than inlining it when the possibility of dynamic calls exists.
We know that C++ doesn't allow templated virtual function in a class. Anyone understands why such restriction?
Short answer: Virtual functions are about not knowing who called whom until at run-time, when a function is picked from an already compiled set of candidate functions. Function templates, OTOH, are about creating an arbitrary number of different functions (using types which might not even have been known when the callee was written) at compile-time from the callers' sides. That just doesn't match.
Somewhat longer answer: Virtual functions are implemented using an additional indirection (the Programmer's General All-Purpose Cure), usually implemented as a table of function pointers (the so-called virtual function table, often abbreviated "vtable"). If you're calling a virtual function, the run-time system will pick the right function from the table. If there were virtual function templates, the run-time system would have to find the address of an already compiled template instance with the exact template parameters. Since the class' designer cannot provide an arbitrary number of function template instances created from an unlimited set of possible arguments, this cannot work.
How would you construct the vtable? Theoretically you could have an infinite number of versions of your templated member and the compiler wouldn't know what they might be when it creates the vtable.
The other answers have already mentionned that virtual functions are usually handled in C++ by having in the object a pointer (the vptr) to a table. This table (vtable) contains pointer to the functions to use for the virtual members as well as some other things.
The other part of the explanation is that templates are handled in C++ by code expansion. This allow explicit specialization.
Now, some languages mandate (Eiffel -- I think it is also the case of Java and C#, but my knowledge of them is not good enough to be authoritative) or allow (Ada) an shared handling of genericity, don't have explicit specialization, but would allow virtual template function, putting template in libraries and could reduce the code size.
You can get the effect of shared genericity by using a technique called type erasure. This is doing manually what compilers for shared genericity language are doing (well, at least some of them, depending on the language, other implementation techniques could be possible). Here is a (silly) example:
#include <string.h>
#include <iostream>
#ifdef NOT_CPP
class C
{
public:
virtual template<typename T> int getAnInt(T const& v) {
return getint(v);
}
};
#else
class IntGetterBase
{
public:
virtual int getTheInt() const = 0;
};
template<typename T>
class IntGetter: public IntGetterBase
{
public:
IntGetter(T const& value) : myValue(value) {}
virtual int getTheInt() const
{
return getint(myValue);
}
private:
T const& myValue;
};
template<typename T>
IntGetter<T> makeIntGetter(T const& value)
{
return IntGetter<T>(value);
}
class C
{
public:
virtual int getAnInt(IntGetterBase const& v)
{
return v.getTheInt();
}
};
#endif
int getint(double d)
{
return static_cast<int>(d);
}
int getint(char const* s)
{
return strlen(s);
}
int main()
{
C c;
std::cout << c.getAnInt(makeIntGetter(3.141)) + c.getAnInt(makeIntGetter("foo")) << '\n';
return 0;
}
I think it's so that compilers can generate vtable offsets as constants (whereas references to non-virtual functions are fixups).
When you compile a call to a template function, the compiler usually just puts a note in the binary, effectively telling the linker "please replace this note with a pointer to the correct function". The static linker does something similar, and eventually the loader fills in the value once the code has been loaded into memory and its address is known. This is called a fixup, because the loader "fixes up" the code by filling in the numbers it needs. Note that to generate the fixup, the compiler doesn't need to know what other functions exist in the class, it just needs to know the munged name of the function it wants.
However with virtual functions, the compiler usually emits code saying "get the vtable pointer out of the object, add 24 to it, load a function address, and call it". In order to know that the particular virtual function you want is at offset 24, the compiler needs to know about all the virtual functions in the class, and what order they're going to appear in the vtable. As things stand, the compiler does know this, because all the virtual functions are listed right there in the class definition. But in order to generate a virtual call where there are templated virtual functions, the compiler would need to know at the point of the call, what instantiations there are of the function template. It can't possibly know this, because different compilation units might instantiate different versions of a function template. So it couldn't work out what offset to use in the vtable.
Now, I suspect that a compiler could support virtual function templates by emitting, instead of a constant vtable offset, an integer fixup. That is, a note saying "please fill in the vtable offset of the virtual function with this munged name". Then the static linker might fill in the actual value once it knows what instantiations are available (at the point where it removes duplicate template instantiations in different compilation units). But that would impose a serious burden of work on the linker to figure out vtable layouts, which currently the compiler does by itself. Templates were deliberately specified to make things easier on implementers, in the hope that they might actually appear in the wild some time before C++0x...
So, I speculate that some reasoning along these lines led the standards committee to conclude that virtual function templates, even if implementable at all, were too difficult to implement and therefore could not be included in the standard.
Note that there's a fair bit of speculation in the above even before I try to read the minds of the committee: I am not the writer of a C++ implementation, and nor do I play one on television.