I have a virtual function that is implemented in a base class A.
This function has a loop in it. A derived class B is available but does not override the virtual function as the code is the same for any derived class.
Well, however, I need an additional condition check inside that virtual function (local_policy) that should be called depending on class type (base or derived).
Now, I could implement another virtual member function and override it in the derived class however as the call happens inside of a loop the virtual overhead should be minimized, so I thought I rather use a function template and specialize it for any derived classes.
Now the problem is that I am passing *this pointer to the function template from within foo() and the specialization is never called.
Is the this pointer in this certain case of type A instead of B? I would have guessed it is not and that my specialised function template would be called.
I appreciate any help!
template < typename T >
bool local_policy(const T* mtype) { return true; }
class A
{
public:
virtual void foo()
{
for(..) {
if(local_policy(this)) //This will call the non-specialised template! Why?
{ /* do something */ }
}
}
/* [...] */
}
class B : public A
{
/* [...] */
//foo() is not overridden here
}
//Specialize the function template for class B
template <>
bool local_policy(const B* mtype) { return false; }
main()
{
B* test = new B; if(!B) return;
test->foo();
}
Thanks in advance!
Best
P.S.: I also tried some C++11 using a normal function and a global template with std::enable_if to only enable if it is a derived class. Doesn't matter, also that one is not called as I expected. :-/
C++ does not allow dynamic dispatch based on argument types -- function overload resolution is always based on the static type of the expression. In your example, the static type of this with always be A *, even when it points at a B, so your specialized function will never be called.
If you want dynamic dispatch, you must use a virtual function, and you can only dynamically dispatch based on the this argument, never any other arguments. If you're worried about the overhead, you can hoist the dynamic call out of the loop and only call it once:
virtual bool local_policy() { return true; }
virtual void foo() {
bool policy = local_policy();
for (..) {
if (policy) {
/* do something */
}
}
}
The compiler can't ever do this optimization on its own, since it doesn't know that you'll never define a derived class that overrides the local_policy function with something that has side effects...
Related
I'm thinking of the way how to call most base virtual function given a pointer to a base class and pointer to most base virtual function of that class. This call should happen in outher module, e.g. Invoker, this module shouldn't know anything about class and function it's calling.
Need to build event-emitting system that will not respect virtuality of the callbacks and call exactly that target's function which address was passed to Invoker.
I want to make mandatory for derived classes to use their own callbacks and subscriptions and in general don't do virtual callback in the hierachy. If client still needs something alike, he can try to use virtual handlers in non-virtual callback of the base class.
I tried all kind of casts. Doesn't help, maybe I use them wrong...
#include <iostream>
class A
{
public:
virtual void Foobar() { std::cout << "A" << std::endl; }
};
class B : public A
{
public:
virtual void Foobar() { std::cout << "B" << std::endl; }
};
using CallbackType = void(A::*)();
void Invoker(A* target, CallbackType function)
{
(target->*function)();
}
int main()
{
A a;
B b;
Invoker(&a, &A::Foobar);
Invoker(&b, &A::Foobar);
b.A::Foobar(); // how to make similar call inside Invoker(&b, &A::Foobar) ?
return 0;
}
The output will be:
A
B
A
I want Invoker somehow to call the most base function, so expected output is:
A
A
A
It's not possible to do this with a pointer to member function. Instead, a lambda would be more appropriate:
Invoker(&b, [](A& a) { a.A::Foobar(); });
You need to rewrite Invoker as a template so that it can accept both lambdas and pointers to members:
template <class F>
void Invoker(A* target, F&& function) {
std::invoke(std::forward<F>(function), *target);
}
From what I know, it's impossible.
You can't call a virtual function in a non-virtual manner through a member function pointer.
Well, the lambda solution presented in the other answer is indeed the way to go.
However, I found a way to do what you want ... sort of. The downside is that it involves a slicing copy of the object:
void Invoker(A* target, CallbackType function)
{
(static_cast<A>(*target).*function)();
}
or
void Invoker(A target, CallbackType function)
{
(target.*function)();
}
Consider the following class definitions:
class foo {
virtual absl::Span<const Input *const> GetInputs() const = 0;
virtual absl::Span<Input *const> GetInputs() {
auto mutable_inputs = GetMutableInputs();
return absl::MakeSpan(mutable_inputs.begin(), mutable_inputs.end());
}
}
class bar : public foo {
absl::Span<const Input *const> GetInputs() const override {
return absl::MakeConstSpan(inputs_);
}
}
When calling bar.GetInputs() it seems like the only implementation found is the the one that returns a span of constant inputs. If I have an instance of bar, and want to create a span of non-const inputs, then I must cast bar to foo, and then call GetInputs.
If I cast bar to foo, then call GetInputs, I am then able to assign the result to a span of non-const inputs. Why does the compiler fail to identify the inherited non-const method with the correct return type? Is there a way to make the subclass identify that method?
In other words, is there a way to make the following code compile:
absl::Span<Input *const> tmp = bar.GetInputs()
If I understand your question, it has nothing to do with virtual functions or "precedence" of const, but is plain old "name hiding".
#include <iostream>
class Base {
public:
virtual void f(int) { std::cout << "Base(int)\n"; }
virtual void f(double) { std::cout << "Base(double)\n"; }
};
class Derived : public Base {
public:
virtual void f(double) { std::cout << "Derived(double)\n"; }
};
int main() {
Derived d;
int x=0;
d.f(x);
}
output: Derived(double)
The issue is, name lookup doesn't work the way it seems you expect.
For a given scope, it searches for names to build an overload set. Within the context of Derived, there is only one f(), so when it's found, the compiler stops searching further for more overloads.
It finds Derived(double) and that's the entire overload set, and so it is selected. When you cast your derived class to a reference to the base, and then call something, both functions (declared in the base) are considered, and overload resolution selects the best match.
Now, normally, for polymorphic types you are working with the objects in terms of pointers/references to the base, so it's not an issue. But if you are calling directly on the derived class (perhaps from inside a member of derived?) then it'll have this issue of the derived declaration hiding the base names.
To make the base names visible in the derived class, it's easy:
class Derived : public Base {
public:
using base::f; // <<<<<<<< just add this
virtual void f(double) { std::cout << "Derived(double)\n"; }
};
you should add
using foo::GetInputs;
in bar class to expose the base class function.
you will be able to call the base class function if the object is non-const
I have a base class First and a derived class Second. In the base class there's a member function create and a virtual function run. In the constructor of Second I want to call the function First::create, which needs access to the implementation of its child class' run() function. A colleague recommended using function templates since First can't know it's child classes explicitly. Sounds weird? Here's some code:
First.h
#pragma once
#include <boost/thread/thread.hpp>
#include <boost/chrono/chrono.hpp>
class First
{
public:
First();
~First();
virtual void run() = 0;
boost::thread* m_Thread;
void create();
template< class ChildClass >
void create()
{
First::m_Thread = new boost::thread(
boost::bind( &ChildClass::run , this ) );
}
};
First.cpp
#include "First.h"
First::First() {}
First::~First() {}
Second.h
#pragma once
#include "first.h"
class Second : public First
{
public:
Second();
~Second();
void run();
};
Second.cpp
#include "Second.h"
Second::Second()
{
First::create<Second>();
}
void Second::run()
{
doSomething();
}
I'm getting an error at First::create<Second>(); saying Error: type name is not allowed. So what's the reason for this error? I assume I didn't quite get the whole mechanics of templates, yet - I'm very new to this topic.
Although you could use CRTP as "suggested" by Kerrek SB and Arne Mertz, here's a solution using a member function template:
class First
{
public:
First();
~First();
virtual void run() = 0;
boost::thread* m_Thread;
// vvvvvvvvvvv this declares a non-template member function `create`
void create(); // (better remove it)
// vvvvvvvvvv this declares a member function template `create`
template< class ChildClass >
void create();
};
For templates, you should provide the definition in the header file, since the definition must be available in every TU where it is required (and not only in one).
The easiest way to do this is to provide the definition of member function templates or members of class templates within the class itself:
class First
{
public:
/* ... */
template< class ChildClass >
void create()
{
// AFAIK, the `bind` is not required
First::m_Thread = new boost::thread(&ChildClass::run,
static_cast<ChildClass*>(this));
}
};
Now, if you want to call this member function template in the Second class, you'd have to explicitly provide the template argument:
void Second::any_function()
{
create<Second>();
}
Some other (possible) issues with your code:
You don't have virtual dtors, therefore deleting a pointer to a base class subobject will invoke UB.
There needs to be a downcast, as &ChildClass::run is of type void (Second::*)().
create is called inside the ctor of Second, which will call Second::run (or whatever template argument you provide), the final override of that function in the class Second. If you override that function in a class derived from Second, that override won't be called in the ctor of Second.
Your dtor of First should either detach or join the boost thread, otherwise std::terminate will be called if the thread is still running when the dtor is called.
run doesn't have to virtual in this example, the exact same code would work w/o run being virtual or even declared in First.
First you have to put template definitions in the header, or the linker will have trouble finding the instantiated templates.
Second: now the pun's done, I assume you derived Second from First<Second>. This is called the "Curiously Recurring Template Pattern" (CRTP).
Since the base class is already specialized and has the type of the derived class carved into its type, there is no need to make any function of it a template (you didn't), and the base class' functions can be just called, without specifying template parameters:
template <class SubClass>
struct First {
void create() {
SubClass& sub = static_cast<SubClass&>(*this);
mThread = make_unique<std::thread>( [&](){sub.run();} );
}
};
struct Second : First<Second> {
Second() { create(); }
void run();
};
Some annotations:
You need not qualify accesses inside First
You can just call create, it's an inherited method, and since Second is no template, there is no need to add qualification or help the compiler with the lookup.
prefer std::thread over boost::thread, it has been in the standard for a while now.
prefer std::unique_ptr over raw pointers with ownership
I prefer lambdas over bind - reads more clear to me.
I made the two classes struct in order to have the member functions public by default and save one line in the example code. There is no difference to class except that.
Say I have the following code:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl(); //A
(*static_cast<Derived*>(this)).foo_impl(); //B
}
};
class Derived : public Base<Derived> {
private:
void foo_impl() {
bar();
}
};
A few questions:
Will line A generate a virtual function call? Although the majority of what I can find on the internet recommends doing things this way, to me I don't see how the compiler can do static dispatch considering that a pointer to Derived could still actually point to an object of type Derived2 where Derived2 : public Derived.
Does line B fix the issue I brought up in my previous point (if applicable)? It seems like it would, considering that now the call is not on a pointer any more and thus using *. would avoid a virtual function call. But if the compiler treats the dereferenced cast as a reference type, it could still generate a virtual function call... in that case, what is the workaround?
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
Will line A generate a virtual function call?
Yes. foo_impl() is virtual and Derived overrides it. Even though foo_impl() in Derived is not explicitly tagged as virtual, it is in the base class, and this is enough to make it a virtual function.
Does line B fix the issue I brought up in my previous point (if applicable)?
No. It does not matter if the call is on a pointer or on a reference: the compiler still won't know whether you are invoking the function foo_impl() on an instance of a class that derives from Derived, or on a direct instance of Derived. Thus, the call is performed through a vtable.
To see what I mean:
#include <iostream>
using namespace std;
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl();
(*static_cast<Derived*>(this)).foo_impl();
}
};
class Derived : public Base<Derived> {
public:
void foo_impl() {
cout << "Derived::foo_impl()" << endl;
}
};
class MoreDerived : public Derived {
public:
void foo_impl() {
cout << "MoreDerived::foo_impl()" << endl;
}
};
int main()
{
MoreDerived d;
d.foo(); // Will output "MoreDerived::foo_impl()" twice
}
Finally:
Does adding the C++11 final keyword to foo_impl() change how the compiler would act in either (or any other relevant) case?
In theory, yes. The final keyword would make it impossible to override that function in subclasses of Derived. Thus, when performing a function call to foo_impl() through a pointer to Derived, the compiler could resolve the call statically. However, to the best of my knowledge, compilers are not required to do so by the C++ Standard.
CONCLUSION:
In any case, I believe what you actually want to do is not to declare the foo_impl() function at all in the base class. This is normally the case when you use the CRTP. Additionally, you will have to declare class Base<Derived> a friend of Derived if you want it to access Derived's private function foo_impl(). Otherwise, you can make foo_impl() public.
The common idiom for the CRTP does not involve declaring the pure virtual functions in the base. As you mention in one of the comments, that means that the compiler will not enforce the definition of the member in the derived type (other than through use, if there is any use of foo in the base, that requires the presence of foo_impl in the derived type).
While I would stick to the common idiom and not define the pure virtual function in the base, but, if you really feel you need to do it, you can disable dynamic dispatch by adding extra qualification:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->Derived::foo_impl();
// ^^^^^^^^^
}
};
The use of the extra qualification Derived:: disables dynamic dispatch, and that call will be statically resolved to Derived::foo_impl. Note that this comes will all of the usual caveats: you have a class with a virtual function and paying the cost of the virtual pointer per object, but you cannot override that virtual function in a most derived type, as the use in the CRTP base is blocking dynamic dispatch...
The extra verbiage in lines A and B have absolutely no effect on
the generated code. I don't know who recommends this (I've never seen
it), but in practice, the only time it might have an effect is
if the function isn't virtual. Just write foo_impl(), and be
done with it.
There is a means of avoiding the virtual function call if the
compiler knows the derived type. I've seen it used for
vector-like classes (where there are different implementations,
e.g. normal, sparse, etc. of the vector):
template <typename T>
class Base
{
private:
virtual T& getValue( int index ) = 0;
public:
T& operator[]( int index ) { return getValue( index ); }
};
template <typename T>
class Derived : public Base<T>
{
private:
virtual T& getValue( int index )
{
return operator[]( index );
}
public:
T& operator[]( index )
{
// find element and return it.
}
};
The idea here is that you normally only work through references
to the base class, but if performance becomes an issue, because
you're using [] in a tight loop, you can dynamic_cast to the
derived class before the loop, and use [] on the derived
class.
Here is an abstraction of my problem.
I want to develop something like this.
class Base {
}
template<typename T>
class TypedBase : Base {
f(const T& input);
}
Now I Want to access the "family" of classes TypedBase via a base pointer and call f.
Something like this
Base* base_ptr;
if (condition) {
base_ptr = new TypedBase<double>();
} else {
base_ptr = new TypedBase<int>();
}
// Int and double are just examples to get the idea
// Then I Want to call
base_ptr->f(4);
This won't compile.
I tried to add an empty virtual function f() to base hoping that vtable would take care of calling the right f() vs. f(T& input) at run time but again didn't work like:
class Base {
virtual f() = 0;
}
So how do you do that? in general I want to have a pointer to a generic TypedBase that allows me to call f(...) via a generic pointer to the family. Any thoughts?
Of course I could do this:
class Base {
// Repeat for every typename
virtual f(int& x) = 0;
virtual f(double& x) = 0;
}
and then each TypedBase will only implements one of them thus I will still get type safety at run time without doing dynamic checking myself in the code. However, If I have N functions to call and M types to work with, then I will have to add M*N abstract functions to the Base class. Any better solution?
You must static_cast (if you know the real type) or dynamic_cast (if you need to check if cast succeeded) the base pointer to right class. If you know what you are passing to method, casting to type that takes that argument should not be a problem. Also casting should work in a template method with right template type.
Does following compile?
template <typename T>
void callF(Base *p, T input) {
TypedBase<T> *tp = dynamic_cast<TypedBase<T>*>(p);
if (tp) tp->f(input);
// else throw exception or call some Base method or return error or...
}
Or less safe, just do:
static_cast<TypedBase<int>*>(base_ptr)->f(1);