Can a Class Member Function Template Be Virtual

Template specialization of pure virtual function

//virtual void func(int a) {} // replace above line with this and it works

Replace the above line and the code compile, doesn't works.

Or, better, works but not as you expect.

The problem is that virtual functions and template functions doesn't mix very well.

So you can't make a template function that directly override a virtual function: if you define func() as a null virtual function

virtual void func(int a) = 0;

the base A class, and all derived classes, become not-instantiable until you don't define an effective virtual func() function.

Defining

virtual void func(int a) {}

the base A class, and all derivate, isn't not-instantiable anymore a you don't need anymore a redefinition of the virtual function.

But the template func() version is not related with virtual function.

When you call b.func(2) in main(), it's the template, not the virtual func() inherited from A, that is called. It's because the template func() "hide" the func() inherited virtual version.

You can "un-hide" the virtual func() version in B adding, in the body of B definition

using A::func;

This way, calling b.func(2); in main(), the virtual version inherited by A is called and the template specialization of func(), so the std::cout <<"hello 2" << std::endl; instruction, ins't executed anymore.

Now... if I understand correctly, you want a template func() function that, in case of T == int join the virtual specialization.

The only way I see is define the virtual override in B

void func (int a) override // override, so necessarily virtual
{ std::cout <<"hello 2" << std::endl; }

and call it from the template specialization

template <>
void B::func<int> (int a)
{ func(a); } // call the virtual override version

The following is a full compiling example

#include <iostream>

struct A
{ virtual void func(int a) = 0; };

struct B : public A
{
void func (int a) override
{ std::cout <<"hello 2" << std::endl; }

template<typename T>
void func (T t)
{ std::cout << "hello" << std::endl; }
};

template <>
void B::func<int> (int a)
{ func(a); }


int main ()
{
B{}.func(2); // call directly virtual func()
B{}.func<int>(2); // call template func() specialization that call virtual func()
}

Are pure virtual methods allowed within a template class?

A class template can indeed contain virtual or pure virtual functions. This was employed by Andrei Alexandresu in "Modern C++ Design" to implement the visitor pattern using templates and type lists. You can see the code here in his Loki library if you're interested.

With most standard C++ implementations, this is fine, because when the template is instantiated the virtual function ends up being one single function. Consequently, the number of slots needed in the vtable can be known within the translation unit, so a vtable can be generated.

As you mentioned, you cannot have a virtual template member function because the number of vtable slots wouldn't be known within the translation unit.

Hope this helps!

Is a virtual function of a template class implicitly instantiated?

Standard section 14.7.1/11 says

It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.

However, for a typical vtable implementation, instantiating any constructor of the class requires a vtable for the class to exist, which must contain a pointer to the specialization's virtual function definition. So in practice the virtual function will probably be instantiated.

Is making a function template specialization virtual legal?

Nice compiler error. For this type of checks I always fallback to the Comeau compiler before going back to the standard and checking.

Comeau C/C++ 4.3.10.1 (Oct 6 2008
11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.
All rights reserved. MODE:strict
errors C++ C++0x_extensions

"ComeauTest.c", line 3: error:
"virtual" is not allowed in a function
template
declaration
template virtual void f();
^

"ComeauTest.c", line 10: error:
"virtual" is not allowed in a function
template
declaration
template virtual void f();
^

Now, as it has been posted by another user, the fact is that the standard does not allow you to define virtual templated methods. The rationale is that for all virtual methods, an entry must be reserved in the vtable. The problem is that template methods will only be defined when they have been instantiated (used). This means that the vtable would end up having a different number of elements in each compilation unit, depending on how many different calls to f() with different types happen. Then hell would be raised...

If what you want is a templated function on one of its arguments and one specific version being virtual (note the part of the argument) you can do it:

class Base
{
public:
template <typename T> void f( T a ) {}
virtual void f( int a ) { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
virtual void f( int a ) { std::cout << "derived" << std::endl; }
};
int main()
{
Derived d;
Base& b = d;
b.f( 5 ); // The compiler will prefer the non-templated method and print "derived"
}

If you want this generalized for any type, then you are out of luck. Consider another type of delegation instead of polymorphism (aggregation + delegation could be a solution). More information on the problem at hand would help in determining a solution.

Virtual method template in Class template C++ [duplicate]

The problem is with F porownywacz, it can't be a template with the pure virtual function.

Virtual member functions can't be templates, to quote clang "virtual cannot be specified on member function templates".

From the cppreference site;

A member function template cannot be virtual, and a member function template in a derived class cannot override a virtual member function from the base class.

The distinction here is essentially ascribed to the virtual functions are a "runtime thing," they are resolved at runtime. The template types are required to be resolved at compile time.

Are you using a conformant complier in the class, what is the teacher using? I would approach you teacher about the issue, quoting the compiler error and to check you are on the same page as your class mates, talk them as well on what error they are getting.


This Q&A contains more detail and some alternatives you may be interested in.

C++ Virtual template method

The problem is that you cannot mix static time polymorphism (templates) with runtime polymorphism easily. The reason for the language disallowing the particular construct in your example is that there are potentially infinite different types that could be instantiating your template member function, and that in turn means that the compiler would have to generate code to dynamically dispatch those many types, which is infeasible.

There are different things that can be done here to get around the limitation, basically either take away the static or the dynamic polymorphism. Removing dynamic polymorphism from the equation could be done by providing a type that is not derived from, to store the <key,value> mappings, and then offering the template that resolves that only at the base level:

class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
m_store.setData( id, value );
}
template <typename T>
T getData( std::string const & id ) const {
return m_store.getData<T>( id );
}
protected:
ValueStore m_store;
};

Now deriving classes can access the ValueStore from the base and there is no need for polymorphism. (This can also be done by implementing the functionality directly in AbstractComputation but it probably makes sense to separate concerns)

The other option is to maintain runtime polymorphism, but remove static polymorphism. This can be done by performing type erasure on the base class and then dispatching to the appropriate (non-templated) function that takes the type-erased arguments. The simplest version of this is just using boost::any:

class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
setDataImpl( id, boost::any( value ) );
}
template <typename T>
T getData( std::string const & id ) const {
boost::any res = getDataImpl( id );
return boost::any_cast<T>( res );
}
protected:
virtual void setDataImpl( std::string const & id, boost::any const & value ) = 0;
virtual boost::any getDataImpl( std::string const & id ) const = 0;
};

How type erasure is implemented under the hood is interesting, but out of the scope here, the important part is that a boost::any is a concrete (non-templated) 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.

Can pure virtual function be Variadic function template? [duplicate]

No. Virtual functions can not be templates at all. That applies to any template (variadic or not), and all virtual functions - pure or not.

If you think about it, it makes sense. Template is not a function, it is a template by which compiler will make a function when it is called. A virtual function, on the other hand, have to be a real function, which compiler calls through function pointer to achieve polymorphic behavior.



Related Topics



Leave a reply



Submit