Check function overwriting in the derived class in CRTP pattern - c++

I'm trying to implement compile-time checking of correct implementation of CRTP pattern.
Here is the code:
#include <iostream>
#include <type_traits>
using namespace std;
#define static_interface_check(BaseClass, DerivedClass, FuncName) \
static_assert(!std::is_same<decltype(&DerivedClass::FuncName), decltype(&BaseClass<DerivedClass>::FuncName)>::value, "CRTP error: function " #BaseClass "::" #FuncName " was not overwritten in the class " #DerivedClass);
template <class T>
class Interface
{
public:
Interface();
void foo1()
{
static_cast<T*>(this)->foo1();
}
void foo2()
{
static_cast<T*>(this)->foo2();
}
};
// Checking inside Interface<T> declaration results in incomplete type error, so I had to move it to the default constructor
template <class T>
Interface<T>::Interface()
{
static_interface_check(Interface, T, foo1);
static_interface_check(Interface, T, foo2);
}
class A: public Interface<A>
{
public:
void foo1() { cout << "A::foo1()" << endl; }
};
template <class T>
void bar(Interface<T> &obj)
{
obj.foo1();
obj.foo2();
}
int main()
{
A a;
bar(a);
return 0;
}
It fails during compilation as expected:
error: static assertion failed: CRTP error: function Interface::foo2
was not overwritten in the class T
But I want to use also function overloading, const and non-const versions of the same function.
The question is: how can I implement it for the interface containing void foo(), void foo(int) and void foo(int) const?

Related

Is it possible to have callback to member of template class?

Is it possible to have callback to member of template class, as depicted above? I mean, I have some template class, there is defined object of another (non-template) class. That object has another member function. I would like to invoke from that member function the member function of template class. Is it feasible?
This is how I understand the problem. A class called 'some_class' (MyAlgorithm) supposed to have a reference to template (AlgorithmConsumer). Since 'some_class' requires only one method, the easiest way is to pass a reference to the function, something like this:
#include <iostream>
#include <functional>
class MyAlgorithm
{
std::function<void()> prepare;
public:
explicit MyAlgorithm(std::function<void()> prepare)
: prepare{prepare}
{}
void do_something()
{
if (prepare)
{
prepare();
}
std::cout << "I did something\n";
}
};
template<typename T>
class AlgorithmConsumer
{
MyAlgorithm algorithm;
public:
AlgorithmConsumer()
: algorithm([this](){prepare();})
{}
void prepare()
{
std::cout << "Preparing...\n";
}
void execute()
{
algorithm.do_something();
}
};
int main()
{
AlgorithmConsumer<int> ac;
ac.execute();
return 0;
}
Hope, this solves your problem.
Here's one way to do it without using std::function
struct B{
template<class T>
void CallTemplateFun(void (T::*funPtr)(), T& instance){
(instance.*funPtr)();
}
};
template<typename T>
class A{
T t;
B b;
public:
A(T v) : t(v){}
void print(){ std::cout << t << std::endl ; }
};
int main(
{
A<int> ai(5);
B b;
b.CallTemplateFun(&A<int>::print, ai);
A<float> af(3.1428f);
b.CallTemplateFun(&A<float>::print, af);
return 0;
}

Using SFINAE to disable template class member function

Is it possible to use SFINAE and std::enable_if to disable a single member function of a template class?
I currently have a code similar to this:
#include <type_traits>
#include <iostream>
#include <cassert>
#include <string>
class Base {
public:
virtual int f() { return 0; }
};
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
assert((std::is_same<T, int>::value));
T val = getValue_();
//return val; --> not possible if T not convertible to int
return *reinterpret_cast<int*>(&val);
}
};
template<typename T>
class MoreDerived : public Derived<T> {
public:
int f() override { return 2; }
};
int main() {
Derived<int> i;
MoreDerived<std::string> f;
std::cout << f.f() << " " << i.f() << std::endl;
}
Ideally, Derived<T>::f() should be disabled if T != int. Because f is virtual, Derived<T>::f() gets generated for any instantiation of Derived, even if it is never called.
But the code is used such that Derived<T> (with T != int) never gets created only as a base class of MoreDerived<T>.
So the hack in Derived<T>::f() is necessary to make the program compile; the reinterpret_cast line never gets executed.
You could simply specialize f for int:
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
return Base::f();
}
};
template <>
int Derived<int>::f () {
return getValue_();
}
No you can't rule out a member function with SFINAE. You could do it with specialisation of your Derived class f member function for convertible Ts to int but that would lead to unnecessary duplication of code. In C++17 however you could solve this with use of if constexpr:
template<typename T> class Derived : public Base {
T getValue_() { return T(); }
public:
int f() override {
if constexpr(std::is_convertible<T, int>::value) return getValue_();
return Base::f();
}
};
Live Demo

Template specialization of inherited member function

We would like to specialize member functions of a base class. However, it does not compile. Does anybody know of any alternative that does compile?
Here is an example
struct Base
{
template<typename T>
void Foo()
{
throw "Foo() is not defined for this type";
}
};
struct Derived : public Base
{
template<>
void Foo<int>() { cout << "Foo<int>()" << endl; } // compile error (cannot specialize members from a base class)
template<>
void Foo<double>() { cout << "Foo<double>()" << endl; } // compile error (cannot specialize members from a base class)
};
Eventually, we solved it using overloading.
Here is how the base class looks like
struct Base
{
template<typename T>
class OfType {}
template<typename T>
void Foo(OfType<T>) { static_assert(false, "Foo is not implemented for this type. Please look in the compiler error for more details."); }
};
struct Derived : public Base
{
using Base::Foo;
void Foo(OfType<int>) { // here comes logic for ints }
void Foo(OfType<double>) { // here comes logic for doubles }
};
Here is an example of client code that uses Foo()
template<typename S>
class ClassThatUsesFoo
{
private: S s;
template<typename T>
void Bar(T item)
{
s.Foo(Base::OfType<T>()); // this is the code that uses Foo
DoSomeStuffWithItem(item);
}
};
void main()
{
ClassThatUsesFoo<Derived> baz;
baz.Bar(12); // this will internally use Foo for ints
baz.Bar(12.0); // this will use Foo for doubles
baz.Bar("hello world"); // this will give a verbose compile error
}
This will compile, except for the call to Foo<char>():
#include <iostream>
#include <string>
using namespace std;
struct Base
{
template<typename T>
void Foo()
{
throw "Foo() is not defined for this type";
}
};
struct Derived : public Base
{
template<typename T> void Foo();
};
template<>
void Derived::Foo<int>() { cout << "Foo<int>()" << endl; }
template<>
void Derived::Foo<double>() { cout << "Foo<double>()" << endl; }
int main()
{
Derived derived;
// this is client code
derived.Foo<int>();
derived.Foo<double>();
derived.Foo<char>(); // this throws
}
If you want the call to Foo<char>() -- or any type not specifically specialized by you -- then this works. If you want a non-specialized implementation that works for all types, then you need to add a non-specialized implementation of Foo() as well:
template<typename T>
void Derived::Foo() { cout << "generic" << endl; }
In response to the discussion with Alex (see comments of the answer of John Dibling), this is what I meant (SSCCE):
#include <iostream>
using namespace std;
struct Base
{
template<typename T>
void Foo()
{
//static_assert(false, "Foo() is not defined for this type");
throw "Foo() is not defined for this type";
}
};
// you can add as many specializations in Base as you like
template <>
void Base::Foo<char>() { cout << "Base::Foo<char>()" << endl; }
struct Derived : public Base
{
// just provide a default implementation of Derived::Foo
// that redirects the call to the hidden Base::Foo
template < typename T >
void Foo()
{ Base::Foo<T>(); }
};
// the specializations for Derived
template<>
void Derived::Foo<int>() { cout << "Foo<int>()" << endl; }
template<>
void Derived::Foo<double>() { cout << "Foo<double>()" << endl; }
struct Derived_wo_specialization : public Base
{
/* nothing */
};
int main()
{
Derived d;
d.Foo<char>();
d.Foo<double>();
Derived_wo_specialization dws;
dws.Foo<char>();
dws.Foo<double>();
}

Template member function (on type T) of non-template class T

I would like to do something like:
class A {
public:
void f();
private:
void g() { };
};
class B {
public:
void f();
private:
void g() { };
};
template<typename T>
void T::f() {
g();
}
int main() {
A a;
B b;
a.f();
b.f();
}
however T::f() does not compile.
Possible workarounds could be making f() non-member:
template<typename T>
void f(T* t);
Or using CRTP: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
But is there no C++ syntax to do as above?
EDIT: I have a big function f() whose code is shared by the 2 classes A and B. A and B have the same interface, which f() uses. However, because we are not using runtime polimorphism (i.e, virtual functions), the corpus of f() needs to be instantiated twice at compile time, once for A and once for B. Templates are made exactly for this purpose. The function f(), in my case, should be template function whose template type is the type of *this.
Free function is the correct answer. You should prefer free functions over member functions anyway, for this exact reason: you extend the interface without intruding on the class.
In this case, a free function with an unconstrained template is a bit ugly, because you only need it to work for two cases, not all cases. You should do something like this:
namespace detail
{
template <typename T>
void f(T* t)
{
// implement stuff
}
}
void f(A* x)
{
detail::f(x);
}
void f(B* x)
{
detail::f(x);
}
Now you can restrict access to that function via overloading.
Here is an example using a free function and retaining the instance.f() syntax. The function needs to be marked as a friend in order to access the private methods:
#include <iostream>
namespace details
{
template<class T>
static void f_impl(T* _this)
{
_this->g();
}
}
class A {
public:
template<class T> friend void details::f_impl(T*);
void f()
{
details::f_impl(this);
}
private:
void g()
{
std::cout << "A" << std::endl;
}
};
class B {
public:
template<class T> friend void details::f_impl(T*);
void f()
{
details::f_impl(this);
}
private:
void g()
{
std::cout << "B" << std::endl;
}
};
int main() {
A a;
B b;
a.f();
b.f();
}

How do you overload templated function (specialized) in child class?

I have a base class with a templated function that has the general templated type, as well as specialized version.
#ifndef BASE_CLASS
#define BASE_CLASS
#include <iostream>
using namespace std;
struct Type1
{
};
struct Type2
{
};
class baseClass
{
public:
template<class Type>
void doStuff(Type & t)
{
templateFunction(t);
}
template<class Type>
void templateFunction(Type & t);
};
template<class Type>
void baseClass::templateFunction(Type & t)
{
cout << "This is the generic function!" << endl;
}
template<>
void baseClass::templateFunction(Type1 & t)
{
cout << "This is the specialized function: - Type1" << endl;
}
#endif
I also have a child class, that inherits from "baseClass". However, the child class requires different functionality for that specialization.
#ifndef CHILD_CLASS
#define CHILD_CLASS
#include "BaseClass.h"
class ChildClass : public baseClass
{
public:
};
template<>
void ChildClass::templateFunction(Type1 & t)
{
cout << "We overloaded the specialized template function for type 1!" << endl;
}
#endif
The above does not compile:
ChildClass.h:13: error: no member function âtemplateFunctionâ declared in âChildClassâ
ChildClass.h:13: error: invalid function declaration
If I change the "overloaded" function to:
template<>
void baseClass::templateFunction(Type1 & t)
{
cout << "We overloaded the specialized template function for type 1!" << endl;
}
I get:
ChildClass.h:13: error: redefinition of âvoid baseClass::templateFunction(Type&) [with Type = Type1]â
BaseClass.h:36: error: âvoid baseClass::templateFunction(Type&) [with Type = Type1]â previously declared here
How do I properly overload specialized template functions in child classes?
For reference, the main:
#include "BaseClass.h"
#include "ChildClass.h"
int main()
{
Type1 first;
Type2 second;
baseClass theBaseClass;
ChildClass theChildClass;
theBaseClass.doStuff(first);
theBaseClass.doStuff(second);
theChildClass.doStuff(first);
theChildClass.doStuff(second);
return 0;
}
On the suggestion of: Kerrek SB, I've changed the ChildClass to:
#ifndef CHILD_CLASS
#define CHILD_CLASS
#include "BaseClass.h"
class ChildClass : public baseClass
{
public:
template<class Type>
void templateFunction(Type & t);
};
template<>
void ChildClass::templateFunction(Type1 & t)
{
cout << "We overloaded the specialized template function for type 1!" << endl;
}
#endif
The output:
This is the specialized function: - Type1
This is the generic function!
This is the specialized function: - Type1
This is the generic function!
I was hoping for:
This is the specialized function: - Type1
This is the generic function!
We overloaded the specialized template function for type 1!
This is the generic function!
So this still doesn't work.
The reason why it still doesn't work the way you wanted to is that the function is not virtual in the parent class. However, it is not possible to have a virtual template function.
I see two main options:
as rhalbersma suggested, make the class itself template and then override the desired method s (which now are NOT template) in the child class.
for the specialized method, just write a new method, with a different name, that does whatever you need.
But I'm sure someone will come up with a better idea... =)
You could make a template class with a virtual function like this:
template<typename T>
class B
{
virtual void f() { std::cout << "base template implementation \n"; }
};
template<>
class B<Type1>
{
virtual void f() { std::cout << "base specialized implementation \n"; }
};
template<typename T>
class D: public B<T>
{
virtual void f() { std::cout << "derived template implementation \n"; }
};
template<>
class D<Type1>: public B<Type1>
{
virtual void f() { std::cout << "derived specialized implementation \n"; }
};
B<Type1> b1;
B<Type2> b2;
D<Type1> d1;
D<Type2> d2;
b1.f();
b2.f();
d1.f();
d2.f();
Now there are 2 independent dimensions of customization: either the template T, or the dynamic type (B vs D). For each template instantiation, the virtual functions can be redefined.
More common is to let B be a regular class with pure virtual functions (i.e. an interface), and let D be a template class deriving from B. This lets you redefine the virtual functions of B in a different way for each template instantiation of D (with a suitable default).