I have something like the attached. I basically have a Doer class in which I want to call Func() from it's member without using virtual or with the least code duplication possible. Also, boost is not an option either. I know the example may not be so clear but I hope you get the idea. B
class Base { // a bunch of shared base functionality. Cannot be instantiated by itself }
class D1 : public Base
{
void Func();
}
class D2 : public Base
{
void Func();
}
//----
class Doer
{
Doer(Base* b) : base(b) { }
void DoIt()
{
base->Func();
}
Base* base;
}
Well, you can make Doer templated:
template<class T>
class Doer
{
public:
Doer(T* b) : base(b) { }
void DoIt()
{
base->Func();
}
private:
T* base;
};
But for this I would just add a virtual void Func() to Base instead.
Note that you'll probably want to make Func public in either case :-)
What about this approach:
class Base { // a bunch of shared base functionality. Cannot be instantiated by itself
~Base() { //stuff }
void Func();
}
class D1 : public Base
{
void Func();
}
class D2 : public Base
{
void Func();
}
//----
class Doer
{
Doer(Base* b) : base(b) { }
void DoIt()
{
base->Func();
}
Base* base;
}
Since Func() isn't virtual and is being overloaded by the children, there shouldn't be a vtable or any incurred performance penalty right?
Also, the destructor needs to be called on the base class, but declaring it virtual will impose a vtable?
Can anyone clarify?
Thanks
You can use mixins! They're good for optimization (lots of inlining opportunities and no virtual method calls), but sometimes a little hard to reason about. Here's your example implemented with mixins:
template<class Base> class Doer : Base {
public:
Doer() {}
void DoIt() {
this->Func();
}
};
class D1 {
public:
void Func() {
cout<<"Hello from D1"<<endl;
}
};
class D2 {
public:
void Func() {
cout<<"Hello from D2"<<endl;
}
};
Using this is a little different, since the Doer is same as your Base class instance. The following program:
Doer<D1> *d1 = new Doer<D1>();
Doer<D2> *d2 = new Doer<D2>();
d1->DoIt();
d2->DoIt();
Produces the output:
Hello from D1
Hello from D2
This has the obvious drawback that D1 and D2 aren't forced to implement the "Func" method. If you forget it, you'll get an oh-so-handy C++ template instantiation error instead of "method not found." Clang is a great choice if you're going to be using templates frequently, since you get much more helpful compiler errors than with g++. Another drawback is with constructors: Doer defines the default constructor, but doesn't expose D1's constructor. C++11 allows for constructor inheritance, so this issue can be avoided with a compiler flag.
in fact you don't need to parameterize the whole Doer class. This will work just fine (close to what ccurtsinger was suggesting):
class Base {
public:
void Func() {};
};
class B1 {
public:
void Func() { cout << "in B1::Func" << endl;}
};
class B2 {
public:
void Func() { cout << "in B2::Func" << endl;}
};
class Doer {
public:
template <class B> void Do(B *pb) {pb->Func();}
};
int main() {
B1 b1;
B2 b2;
Doer d;
d.Do<B1>(&b1);
d.Do<B2>(&b2);
return 0;
}
But really there's a bigger question: from the code you said you finally used it seems like at compile time you know exactly which derived classes objects you're dealing with, so code like:
for(auto i = begin(B1_container); i != end(B1_container); ++i) {
i->Func();
}
for(auto j = begin(B2_container); j != end(B2_container); ++j) {
j->Func();
}
should do the trick.
What I'm saying is - you either know in advance that you're working with B1-s here and B2-s there and there's no additional cost for Func() invocation, OR you don't know which one you are to deal with next and then you need to check it's dynamic type of some type of trait or whatever and that's an 'if' and thus branching and thus mispredictions and overhead. Notice, I'm not adding the cost of a function call, which is there in both cases regardless.
Related
So shortly the situation is like this
class Base
{
public:
Base() { setZero();}
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values";}
};
class Derived : public Base
{
public:
Derived () { }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values";
}
};
setZero is public an is called form different places, also it has some logic, not just assignments, as Base and Derived classes are quite large.
But it's all doesn't work as intended as dynamic binding doesn't work when function is called from the constructor.
I see the solution to duplicate code from setZero to the consructors, but duplication of code is a bad thing. Is there some other solutions?
You might have factory to have "post-call", something like:
template <typename T, typename ... Ts>
T CreateBaseType(Ts&&... args)
{
T t(std::forward<Ts>(args)...);
t.setZero();
return t;
}
TL;DR - two phase construction sucks. Try to make your constructors construct stuff, and not call any virtual methods, or require it in order to function.
If you want initialization to occur after object construction (including vtables), you need to have a separate initialization phase on your objects.
A probably better way to handle this is this:
class Base
{
int x = 0; // notice the =0 here
public:
Base() {} // nothing
virtual setZero() {*this = Base{};} // use operator= to assign zeros
};
class Derived : public Base
{
double d = 0.; // notice the = 0. here
public:
Derived () { } // nothing
void setZero() override {*this = Derived{};}
};
we can avoid rewriting setZero as well:
template<class D, class B=void>
struct SetZero:B {
void setZero() override {
*static_cast<D*>(this) = D{};
}
};
template<class D>
struct SetZero<D,void> {
virtual void setZero() {
*static_cast<D*>(this) = D{};
}
};
now we can:
class Base:public SetZero<Base>
{
int x = 0; // notice the =0 here
public:
A() {} // nothing
};
class Derived : public SetZero<Derived, Base>
{
double d = 0.; // notice the = 0. here
public:
Derived () { } // nothing
};
and setZero is written for us.
The DRY here is that default construction zeros, and we put the zeros right next to where we declare variables. setZero then just becomes a helper method to copy over yourself with a default constructed object.
Now, exposing value semantics copy/move operations on a class with a vtable is a bad plan. So you probably want to make the copy/move protected and add friend declarations.
template<class D, class B=void>
struct SetZero:B {
void setZero() override {
*static_cast<D*>(this) = D{};
}
SetZero()=default;
protected:
SetZero(SetZero&&)=default;
SetZero& operator=(SetZero&&)=default;
SetZero(SetZero const&)=default;
SetZero& operator=(SetZero const&)=default;
~SetZero() override=default;
};
template<class D>
struct SetZero<D,void> {
virtual void setZero() {
*static_cast<D*>(this) = D{};
}
SetZero()=default;
protected:
SetZero(SetZero&&)=default;
SetZero& operator=(SetZero&&)=default;
SetZero(SetZero const&)=default;
SetZero& operator=(SetZero const&)=default;
virtual ~SetZero()=default;
};
so those get longer.
In Base and Derived as they have vtables, you are recommended to add
protected:
Derived(Derived&&)=default;
Derived& operator=(Derived&&)=default;
};
to block external access to move/copy construct and move/copy assign. This is advised regardless of how you write setZero (any such move/copy is going to risk slicing, so exposing it to all users of your class is a bad plan. Here I make it protected, because setZero relies on it to make zeroing DRY.)
Another approach is a two-phase construction. In it, we mark all "raw" constructors are protected.
class Base {
int x;
protected:
Base() {} // nothing
public:
virtual setZero() { x = 0; }
};
we then add a non-constructor constructor:
class Base {
int x;
protected:
Base() {} // nothing
public:
template<class...Ts>
static Base Construct(Ts&&...ts){
Base b{std::forward<Ts>(ts)...};
b.setZero();
}
virtual setZero() { x = 0; }
};
and external users have to Base::Construct to get a Base object. This sort of sucks, because our type is no longer regular, but we already have vtable, which makes it unlikely to be regular in the first place.
We can CRTP it;
template<class D, class B=void>
struct TwoPhaseConstruct:B {
template<class...Ts>
D Construct(Ts&&...ts) {
D d{std::forward<Ts>(ts...));
d.setZero();
return d;
}
};
template<class D>
struct TwoPhaseConstruct<D,void> {
template<class...Ts>
D Construct(Ts&&...ts) {
D d{std::forward<Ts>(ts...));
d.setZero();
return d;
}
};
class Base:public TwoPhaseConstruct<Base> {
int x;
protected:
Base() {} // nothing
public:
virtual setZero() { x = 0; }
};
class Derived:public TwoPhaseConstruct<Derived, Base> {
int y;
protected:
Derived() {} // nothing
public:
virtual setZero() { Base::setZero(); y = 0; }
};
and here goes down the rabbit hole, if you want to make_shared or similar we have to add a helper type.
template<class F>
struct constructor_t {
F f;
template<std::constructible_from<std::invoke_result_t<F const&>> T>
operator T()const&{ f(); }
template<std::constructible_from<std::invoke_result_t<F&&>> T>
operator T()&&{ std::move(f)(); }
};
which lets us
auto pBase = std::make_shared<Base>( constructor_t{[]{ return Base::Construct(); }} );
but how far down the rabbit hole do you want to go?
Alternatively to the other answers, separating functionality from API lets you use the general flow you want while dodging the whole "using the vtable in the constructor" issue.
class Base
{
public:
Base() {
setZeroImpl_();
}
virtual void setZero() {
setZeroImpl_();
}
private:
void setZeroImpl_() {
std::cout << "Set all Base class values to zeros (default) values";
}
};
class Derived : public Base
{
public:
Derived () {
setZeroImpl_();
}
void setZero() override {
Base::setZero();
setZeroImpl_();
}
private:
void setZeroImpl_() {
std::cout << "Set all Derived class values to zeros (default) values";
}
};
You could solve it this way:
#include <iostream>
class Base
{
public:
Base() { Base::setZero();}
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values\n";}
protected:
Base(bool) {};
};
class Derived : public Base
{
public:
Derived () : Base(true) { Derived::setZero(); }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values\n";
}
};
What I have done, is the following:
Make clear which setZero() method is called by which constructor
Added call to setZero()also from the Derived constructor
Added a protected Base constructor that does not call its setZero() method, and calling this constructor from Derived's constructor, so that Base::setZero()is called exactly once during creation of a Derived object.
By doing it this way, you can create Base or Derived and call zerZero() as intended.
You could implement a simple factory method in your Derived class and remove the setZero() calls from the constructors alltogether. Then making the constructors non-public will tell consumers of the class to use the factory method for proper instantiation instead of the constructor. Something like this:
class Base
{
protected:
Base() { }
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values";}
};
class Derived : public Base
{
public:
static Derived createInstance()
{
Derived derived;
derived.setZero();
return derived;
}
private:
Derived() { }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values";
}
};
And then create your instance of Derived somehow like this:
int main()
{
Derived derived = Derived::createInstance();
// do something...
return 0;
}
With this approach you can also make sure that no one can create an instance of your class that is not in a valid state.
Note: Don't know if you use the base class at some places directly but if this is the case you could provide a factory method for it as well.
If I understand your question correctly, then what you need to do is below simply
#include <iostream>
using std::cout;
using std::endl;
class Base
{
void init() {std::cout << "Set all Base class values to zeros (default) values" << endl;}
public:
Base() {init(); }
virtual void setZero() {init();}
};
class Derived : public Base
{
void init() { std::cout << "Set all Derived class values to zeros (default) values" << endl; }
public:
Derived () { init(); }
void setZero() override {
Base::setZero();
init();
}
};
int main()
{
Derived d1;
cout << endl;
d1.setZero();
}
You wrote the below statement for your code
But it's all doesn't work as intended as dynamic binding doesn't work when function is called from the constructor.
Yes, the virtual behavior will not work, when calling setZero() from the base class constructor, and the reason is that derived class has not been constructed yet.
What you need is to initialize each class when its constructed, and that should happen in there respective constructors, and that is what we do in the above code.
Base class constructor will call its own setZero, derived class constructor will call its own setZero.
And you will continue to do the same thing, if you derive any further class from Derived class.
I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.
I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.
The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}
Let's consider the following code:
#include <iostream>
class Base
{
public:
void foo() //Here we have some method called foo.
{
std::cout << "Base::foo()\n";
}
};
class Derived : public Base
{
public:
void foo() //Here we override the Base::foo() with Derived::foo()
{
std::cout << "Derived::foo()\n";
}
};
int main()
{
Base *base1 = new Base;
Derived *der1 = new Derived;
base1->foo(); //Prints "Base::foo()"
der1->foo(); //Prints "Derived::foo()"
}
If I have the above stated classes, I can call the foo method from any of Base or Derived classes instances, depending on what ::foo() I need. But there is some kind of problem: what if I need the Derived class instance, but I do need to call the Base::foo() method from this instance?
The solve of this problem may be next:
I paste the next method to the class Derived
public:
void fooBase()
{
Base::foo();
}
and call Derived::fooBase() when I need Base::foo() method from Derived class instance.
The question is can I do this using using directive with something like this:
using Base::foo=fooBase; //I know this would not compile.
?
der1->Base::foo(); //Prints "Base::foo()"
You can call base class method using scope resolution to specify the function version and resolve the ambiguity which is useful when you don't want to use the default resolution.
Similar (Not exactly same case) example is mentioned # cppreference
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}
when running the following code on MSVC 2013, x64 Debug config, it will show up a message box with this famous error message when quitting the main() function
"Run-Time Check Failure #2 - Stack around the variable 'tmp' was corrupted.".
The question I can't answer is: Why?
note that no error message will occur when running on Release config. (why?)
disclaimer: this is just a sample code, meaning that I'm trying to use this same design on other classes (one base and several derived) with much more methods and template arguments and with a much more complex data type than the basic int*.
#include <iostream>
template <class T>
class base {
public:
base() {
static_cast<T*>(this)->setData();
}
~base() {
static_cast<T*>(this)->destroyData();
}
void print() {
static_cast<T*>(this)->print_int();
}
};
class derived : public base<derived> {
public:
void setData() {
x = new int();
}
void destroyData() {
delete x;
x = nullptr;
}
void print_int() {
std::cout << "x = " << *x << std::endl;
}
private:
derived() {}
derived(const derived& other) {}
inline derived& operator= (derived copy) {}
int *x;
};
int main() {
base<derived> tmp;
tmp.print();
return 0;
}
EDIT:
#Yakk if I understand correctly, you propose as solution this code:
#include <iostream>
template <class T>
class mix_in : public T
{
public:
mix_in() { (this)->setData(); }
~mix_in() { (this)->destroyData(); }
void print() { (this)->print_int(); }
};
class foo
{
public:
void setData()
{
x = new int();
}
void destroyData()
{
delete x;
x = nullptr;
}
void print_int()
{
std::cout << "x = " << *x << std::endl;
}
foo() {}
private:
int *x;
};
int main()
{
mix_in<foo> tmp;
tmp.print();
return 0;
}
It works just fine, thank you. I'll probably use this pattern since it seems that there's no solution to use CRTP for what I'm trying to do.
But I still would like to understand why the stack corruption happens. In spite of all the discussion around use or not use CRTP for all things, I'd like to understand very precisely why it happens.
Thank you again.
As for your code shown in main():
int main() {
base<derived> tmp;
tmp.print();
return 0;
}
base<derived> tmp; that's wrong usage of this pattern, you wanted derived tmp;.
The point of the CRTP is that the derived class is injected to the base class and provides implementations for certain features that are resolved at compile time.
The base class is inherently intended, to be instantiated exclusively via inheritance. Thus you should ensure not to have any instantiations outside an inheritance context.
To avoid users of your implementation trapped by this misconception, make base's constructor(s) protected:
template <class T>
class base {
public:
~base() {
static_cast<T*>(this)->destroyData();
}
// ...
protected:
T* thisPtr;
base() : thisPtr(static_cast<T*>(this)) {
}
};
NOTE: The base class shouldn't call any methods dependent on the fully initialized derived class methods from within your base class constructor though, as you have shown with your sample (static_cast<T*>(this)->setData();)!
You may store the reference to T* for later use though, as shown in the above sample.
class derived : public base<derived> {
public:
derived() {
setData();
}
void destroyData() {
delete x;
x = nullptr;
}
void print_int() {
std::cout << "x = " << *x << std::endl;
}
private: // ????
derived(const derived& other) {}
inline derived& operator= (derived copy) {}
int *x;
};
Also it's a bit unclear, why you want to hide copy constructor and assignment operator for your class?
tmp is a base<derived>, not a derived. The point of CRTP is that the base class "knows" the object's actual type because it's being passed as the template parameter, but if you manually create a base<derived>, then the base class functions would think the object is a derived, but it isn't - it's just a base<derived>. Weird things (undefined behavior) happen as a result. (As noted in the other answer, you are also printing out something without setting it...)
As to your second question, the checks generated by MSVC to detect those sorts of programmer errors appears to be turned off in Release mode, presumably for performance reasons.
template <class T> class mix_in:public T {
public:
base() { (this)->setData(); }
~base() { (this)->destroyData(); }
void print() { (this)->print_int(); }
};
Rename derived to foo. Do not inherit from mix_in or base in foo.
Swap base for mix_in in main.
CRTP is not the solution to all problems.
You say in comments,
the derived class will never be instantiated, its constructor is never called
Others have already pointed out the undefined use of an unconstructed object. To be specific, consider that int *x is a derived member, and your base<derived> usage generates calls, in sequence, to derived::set_data(), derived::print_int(), and on exit derived::destroy_data(), all member functions of an object that doesn't exist, referring to a member for which you've never allocated space1.
But I think what you're after is wholly legitimate. Factoring code is the whole point of templates and inheritance, i.e. to make important code easier to even identify let alone comprehend, and any later refactoring easier to do, by abstracting out boilerplate.
So:
template < class T >
struct preconstruction_access_subset {}; // often left empty
template < class T, class S = preconstruction_access_subset<T> >
struct base : S {
base() { S::setData(); }
~base() { S::destroyData(); }
void print() { S::print_int(); }
};
// ... later ...
#include <iostream>
struct derived;
template<> struct preconstruction_access_subset<derived> {
// everything structors in `base<derived>` need
int *x;
void setData() { x = new int; }
void destroyData() { delete x; }
void print_int() { std::cout << x << '\n'; }
};
struct derived : base<derived> {
// everything no structors in any base class need to access
};
int main() {
base<derived> tmp;
tmp.print();
}
In this example print_int() isn't actually accessed during construction, so you could drop it back into the derived class and access it from `base as for "normal" CRTP, it's just a matter of what's clearest and best for your actual code.
1 That isn't the only problem, just the only one that's apparent without considering any reliance the compiler itself might need to place on the construction sequence. Think independent-name binding and potential inlining and the ways object identity morphs during {de,con}struction and compiler code factoring for all the potential template/inheritance/member-function/etc. combinations. Don't just hoist the int *x; to solve the current symptom, that would just kick the trouble farther down the road even if yours doesn't get that far yet.
If you have something like this:
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "into func";
}
};
class C : public B
{
};
int main()
{
C c;
c.func();
return 0;
}
Is func() dynamically dispatched?
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Edit: My code didn't compile? Sorry guys. I'm kinda ill right now. My new code also doesn't compile, but that's part of the question. Also, this question is for me, not the faq.
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "in B::func()\n";
}
};
class C : public B
{
public:
virtual void func() {
std::cout << "in C::func()\n";
}
};
class D : public A<D> {
void func() {
std::cout << "in D::func()\n";
}
};
class E : public D {
void func() {
std::cout << "in E::func()\n";
}
};
int main()
{
C c;
c.func();
A<B>& ref = c;
ref.func(); // Invokes dynamic lookup, as B declared itself virtual
A<D>* ptr = new E;
ptr->func(); // Calls D::func statically as D did not declare itself virtual
std::cin.get();
return 0;
}
visual studio 2010\projects\temp\temp\main.cpp(8): error C2352: 'B::func' : illegal call of non-static member function
visual studio 2010\projects\temp\temp\main.cpp(15) : see declaration of 'B::func'
visual studio 2010\projects\temp\temp\main.cpp(7) : while compiling class template member function 'void A<T>::func(void)'
with
[
T=B
]
visual studio 2010\projects\temp\temp\main.cpp(13) : see reference to class template instantiation 'A<T>' being compiled
with
[
T=B
]
I'm not sure I understand what you're asking, but it appears you are missing the essential CRTP cast:
template<class T>
struct A {
void func() {
T& self = *static_cast<T*>(this); // CRTP cast
self.func();
}
};
struct V : A<V> { // B for the case of virtual func
virtual void func() {
std::cout << "V::func\n";
}
};
struct NV : A<NV> { // B for the case of non-virtual func
void func() {
std::cout << "NV::func\n";
}
};
If T does not declare its own func, this will be infinite recursion as self.func will find A<T>::func. This is true even if a derived class of T (e.g. DV below) declares its own func but T does not.
Test with different final overrider to show dispatch works as advertised:
struct DV : V {
virtual void func() {
std::cout << "DV::func\n";
}
};
struct DNV : NV {
void func() {
std::cout << "DNV::func\n";
}
};
template<class B>
void call(A<B>& a) {
a.func(); // always calls A<T>::func
}
int main() {
DV dv;
call(dv); // uses virtual dispatch, finds DV::func
DNV dnv;
call(dnv); // no virtual dispatch, finds NV::func
return 0;
}
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Somewhat contradictory, isn't it? A user of class A may know nothing about B or C. If you have a reference to an A, the only way to know if func() needs dynamic dispatch is to consult the vtable. Since A::func() is not virtual there is no entry for it and thus nowhere to put the information. Once you make it virtual you're consulting the vtable and it's dynamic dispatch.
The only way to get direct function calls (or inlines) would be with non-virtual functions and no indirection through base class pointers.
Edit: I think the idiom for this in Scala would be class C: public B, public A<C> (repeating the trait with the child class) but this does not work in C++ because it makes the members of A<T> ambiguous in C.
In your particular example, there's no need for dynamic dispatch because the type of c is known at compile time. The call to B::func will be hard coded.
If you were calling func through a B*, then you would be calling a virtual function. But in your highly contrived example, that would get you to B::func once again.
It doesn't make much sense to talk about dynamic dispatch from an A* since A is a template class - you can't make a generic A, only one that is bound to a particular subclass.
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
As others have noticed, it's really hard to make sense of that question, but it made me remember something I have learned a long time ago, so here's a very long shot at answering your question:
template<typename Base> class A : private Base
{
public:
void func()
{
std::count << "A::func";
}
};
Given this, it depends on A's base whether func() is virtual. If Base declares it virtual then it will be virtual in A, too. Otherwise it won't. See this:
class V
{
public:
virtual void func() {}
};
class NV
{
};
class B : public A<V> // makes func() virtual
{
public:
void func()
{
std::count << "B::func";
}
};
class C : public A<NV> // makes func() non-virtual
{
public:
void func()
{
std::count << "C::func";
}
};
Would this happen to answer your question?
Whether the function is dynamically dispatched or not depends on two things:
a) whether the object expression is a reference or pointer type
b) whether the function (to which overload resolution resolves to) is virtual or not.
Coming to your code now:
C c;
c.func(); // object expression is not of pointer/reference type.
// So static binding
A <B> & ref = c;
ref.func(); // object expression is of reference type, but func is
// not virtual. So static binding
A<D>* ptr = new D;
ptr->func(); // object expression is of pointer type, but func is not
// virtual. So static binding
So in short, 'func' is not dynamically dispatched.
Note that :: suppresses virtual function call mechanism.
$10.3/12- "Explicit qualification with
the scope operator (5.1) suppresses
the virtual "call mechanism.
The code in OP2 gives error because the syntax X::Y can be used to invoke 'Y' in the scope of 'X' only if 'Y' is a static member in the scope of 'X'.
Seems you just had to add a little trace and usage to answer your own question...
#include <iostream>
template<typename T> struct A {
void func() {
T::func();
}
};
struct B1 : A<B1> {
virtual void func() {
std::cout << "virtual void B1::func();\n";
}
};
struct B2 : A<B2> {
void func() {
std::cout << "void B2::func();\n";
}
};
struct C1 : B1 { };
struct C2 : B2 { };
struct C1a : B1 {
virtual void func() {
std::cout << "virtual void C1a::func();\n";
}
};
struct C2a : B2 {
virtual void func() {
std::cout << "virtual void C2a::func();\n";
}
};
int main()
{
C1 c1;
c1.func();
C2 c2;
c2.func();
B1* p_B1 = new C1a;
p_B1->func();
B2* p_B2 = new C2a;
p_B2->func();
}
Output:
virtual void B1::func();
void B2::func();
virtual void C1a::func();
void B2::func();
Conclusion: A does take on the virtual-ness of B's func.