As we know in CRTP the derived class inherit base, as final inheritance.
What if we want make the derived class not-final but the 'overriding' functions is 'final'?
Is there any way to make it with static_assert?
Code sample:
template <typename D>
struct A
{
int f()
{
return static_cast<D*>(this)->g();
}
int g();
};
struct B : A<B> // usually final, but we want it inheritable
{
int g() // but this should be 'final'
{
// TODO: ???
return 1;
}
};
struct C : B
{
int g() // this is bad
{
return 2;
}
int h(); // this is permissive
};
#include <iostream>
template <typename D>
void f(A<D>& x)
{
std::cout << x.f() << std::endl;
}
int main()
{
B b;
C c;
f(b); // OK, it's 1
f(c); // BAD, it's 1
return 0;
}
You can use final for two purposes.
From https://en.cppreference.com/w/cpp/language/final
specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from.
You can use
struct B : A<B>
{
virtual int g() final
{
return 1;
}
};
to allow other classes to derive from B but not able to override g().
Another potential side benefit of using final is that an optimizing compiler might be able to resolve the function call at compile time instead of resolving at run time (Thanks #JesperJuhl).
I came up with a solution by using private tag in function signature:
template <typename D>
struct A
{
struct internal_tag
{};
int f()
{
return static_cast<D*>(this)->g({});
}
int g(internal_tag);
};
struct B : A<B>
{
int g(internal_tag)
{
return 1;
}
private:
using A<B>::internal_tag;
};
struct C : B
{
// int g(internal_tag) // int g(internal_tag) is prohibited
// {
// return 2;
// }
int h();
};
Related
I'm trying to deduct a template of a function based on the class of the object invoking the function. How can I do this?
#include <type_traits>
struct B;
template<typename T>
bool f(const T*) { return std::is_same<T, B>::value; }
struct A {
bool g() { return f(this); }
};
struct B:A {};
int main() {
B b_obj;
return b_obj.g(); // returns false
}
Making g virtual doesn't help either.
How can I make b_obj.g() return true?
Both the below ways require modification of the code:
Runtime polymorphism (preferred IMO)
Make the callable function a non-template virtual method of base class. i.e.
struct A {
virtual bool f () { /* code */ }
bool g() { return f(); } // no argument to be passed now!
};
struct B : A { bool f () override { /* code */ } };
Static polymorphism (using CRTP)
template<class Child>
struct A {
bool g() { return f(static_cast<Child*>(this); }
};
struct B : A<B> {};
I have class A that needs to invoke the member functions of template class B. Searching around I found this sample code on this site:
#include <iostream>
template<typename T, typename FType>
void bar(T& d, FType f) {
(d.*f)(); // call member function
}
struct foible
{
void say()
{
std::cout << "foible::say" << std::endl;
}
};
int main(void)
{
foible f;
bar(f, &foible::say); // types will be deduced automagically...
}
That came from this answer:
C++ method name as template parameter
But it doesn't do 100% of what I need. How would the above code be re-written so that:
method bar is a public member of a class and not a stand-alone
function
arguments d and f which are getting passed to method bar are
public members of the same class to which bar is a member,
allowing bar to be of type void (void)
object type foible is a class and not a structure (optional)?
[EDIT 1] My own attempt at the rewrite which meets points 1) and 2) is the following, which is wrong:
#include <iostream>
template<class T, void (T::*FType)()>
class foo {
public:
T obj;
FType f;
void bar(void) {
(obj.*f)(); // call member function
} // end bar
}; // end class foo
struct foible
{
void say()
{
std::cout << "foible::say" << std::endl;
}
};
int main(void)
{
foible f;
foo<foible, void (foible::*)()> c;
c.T = f;
c.Ftype = &foible::say;
c.bar(); // types will be deduced automagically...
}
My goal is to have an object of class type 'A' invoke the methods of object of class type 'B', so that when these methods execute the object of type 'B' can use its 'this' pointer to reference its local data. I want to use function pointers inside class type 'A' so that these only need to be specified once, and I don't want one class to have to be derived from another.
You are making that too complicated. Forget about pointers to methods. Currently there is no reason to use them.
Just do something like this:
template<typename F>
void bar(F f) {
doSomething();
f(someArg);
doSomething();
}
int main(void)
{
foible f;
bar([&f](auto x) { f.someMagicMethod(x); } );
return 0;
}
Note this approach is more flexible and readable than playing around with method pointers.
A step by step solution:
all examples uses the following class and foo function
#include <iostream>
class A
{
public:
void foo(){std::cout<<"foo"<<std::endl;}
};
this sample works without template: just calling the calling A::foo with pointer to A and pointer to A::foo:
class B
{
public:
A *a;
void (A::*p)();
void bar()
{
(a->*p)(); //call A::foo
}
};
int main(void)
{
A a;
B b;
b.a = &a;
b.p = &A::foo;
b.bar();
return 0;
}
The following sample added template class T, the pointer to foo method derived from T.
template <class T>
class C
{
public:
T* t;
void (T::*p)();
C(T &o) : t(&o){}
void bar()
{
(t->*p)();
}
};
int main(void)
{
A a;
C<A> c(a);
c.p = &A::foo;
c.bar();
return 0;
}
in the following, the method pointer was templated too, but I don't see how can it be used since you should know how many argument to give it, but anyway:
template <class T, typename F>
class D
{
public:
T* t;
F p;
D(T &o, F pf) : t(&o),p(pf){}
void bar()
{
(t->*p)();
}
};
int main(void)
{
A a;
D<A, void (A::*)()> d(a, &A::foo);
d.bar();
return 0;
}
Consider the following standard CRTP example:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
If this was regular virtual inheritance I could have mark virtual f and g methods as pure like
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.
You can assert at compile time that the two pointers to member functions are different, e.g.:
template<class Derived>
struct Base {
void g() {
static_assert(&Derived::g != &Base<Derived>::g,
"Derived classes must implement g().");
static_cast<Derived *>(this)->g();
}
};
Here is another possibility:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.
You could use this solution, you can have pure "non-virtual abstract" function, and it maps as much as possible to CRTP this recommendation of H. Sutter:
template<class Derived>
struct Base
{
void f(){static_cast<Derived*>(this)->do_f();}
void g(){static_cast<Derived*>(this)->do_g();}
private:
//Derived must implement do_f
void do_f()=delete;
//do_g as a default implementation
void do_g(){}
};
struct derived
:Base<derived>
{
friend struct Base<derived>;
private:
void do_f(){}
};
You could consider doing something like this instead. You can make Derived a member and either supply it as a template parameter directly each time you instantiate a Base or else use a type alias as I have done in this example:
template<class Derived>
struct Base {
void f() { d.f(); }
void g() { d.g(); }
private:
Derived d;
};
struct FooImpl {
void f() { std::cout << 42 << std::endl; }
};
using Foo = Base<FooImpl>;
int main() {
Foo foo;
foo.f(); // OK
foo.g(); // compile time error
}
Of course Derived is no longer derived so you might pick a better name for it.
Is it possible to implement such behaviour? It does not have to use inheritance, I just want to implement template method design pattern with generic arguments passing (with c++ templates).
class A {
public:
template<typename ...tArgs>
void call(tArgs ...vArgs) {
for (int i = 0; i < 5; ++i)
impl(vArgs...);
}
};
class B : public A {
public:
void impl() {}
void impl(int) {}
};
int main() {
B b;
b.call(); // ok
b.call(1); // ok
b.call(""); // compile error, no method to call inside 'call'
return 0;
}
This is almost a classic example of the CRTP pattern, just a few small changes required:
// A is now a template taking its subclass as a parameter
template <class Subclass>
class A {
public:
template<typename ...tArgs>
void call(tArgs ...vArgs) {
for (int i = 0; i < 5; ++i)
// need to static cast to Subclass to expose impl method
static_cast<Subclass*>(this)->impl(vArgs...);
}
};
// pass B into A template (the "curiously recurring" part)
class B : public A<B> {
public:
void impl() {}
void impl(int) {}
};
int main() {
B b;
b.call(); // ok
b.call(1); // ok
// b.call(""); // will cause compile error, no method to call inside 'call'
return 0;
}
If I have two classes:
class A{
f();
}
class B{
f();
};
I need to assign one of these classes to an object based on a condition like:
define variable
if condition1
variable = A
else
variable = B
and then I would use the assigned variable.f();
You should look toward inheritance and virtual functions.
Code might look like
class Base
{
virtual void f() = 0;
};
class A : public Base
{
virtual void f()
{
//class A realization of f
}
};
class B : public Base
{
virtual void f()
{
//class B realization of f
}
};
And then you can do this
Base* VARIABLE = 0;
if (*condition*)
{
VARIABLE = new A();
}
else
{
VARIABLE = new B();
}
VARIABLE->f();
But it not always a good idea to use inheritance and virtual functions. Your classes A and B should have something in common, at least the meaning of function f().
Provided A and B are meant to be unrelated types (i.e. not part of an inheritance hierarchy), you could use Boost.Variant in combination with the boost::static_visitor<> class to achieve something similar:
#include <boost/variant.hpp>
#include <iostream>
struct A { void f() { std::cout << "A::f();" << std::endl; } };
struct B { void f() { std::cout << "B::f();" << std::endl; } };
struct f_caller : boost::static_visitor<void>
{
template<typename T>
void operator () (T& t)
{
t.f();
}
};
bool evaluate_condition()
{
// Just an example, some meaningful computation should go here...
return true;
}
int main()
{
boost::variant<A, B> v;
if (evaluate_condition())
{
A a;
v = a;
}
else
{
B b;
v = b;
}
f_caller fc;
v.apply_visitor(fc);
}
What you are doing is known in design patterns as the "Factory Pattern". The above answers cover how it should be implemented. You can get more information at How to implement the factory method pattern in C++ correctly and wiki (http://en.wikipedia.org/wiki/Factory_method_pattern).