Template specialization of inherited member function - c++

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>();
}

Related

using intermediate class in a Crtp hierarchy without declaring a new class

I have a hierarchy similar to the following:
#include <iostream>
template<typename DerivedCrtp>
struct A
{
void Print() { std::cout << "A";}
};
struct B : public A<B>
{
};
template<typename DerivedCrtp>
struct C : public A<C<DerivedCrtp>>
{
void Print() { std::cout << "C";}
};
template<typename DerivedCrtp>
struct D : public C<D<DerivedCrtp>>
{
void Print() { std::cout << "D";}
};
struct CFinalized : public C<CFinalized>
{
void Print() { std::cout << "CFinal";}
};
template<typename DerivedCrtp = CSmart<>>
struct CSmart : public A<C<DerivedCrtp>>
{
void Print() { std::cout << "C";}
};
int main()
{
C<int> c;
D<int> d;
CFinalized cf;
c.Print();
d.Print();
cf.Print();
}
Because C is using crtp I can't directly use it without providing the self derived type DerivedCrtp.
In order to use it I need to "finalize" it's type (see CFinalized).
It works but every time I need to use a class part of that hierarchy (that in my real code is deeper and contains several more template parameters), I need to explicitly declare a new class.
Is there a smarter way to do this?

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

How to declare a template method of a template base class using 'using'?

Two methods for accessing template base class members are described here. When the base class member itself is a template, accessing it using the first method (this->) above is described here. Is there a way to use the second method (using xxxx) in this scenario as well?
For example, in the code below, is it possible to replace "????" with something to make the code work?
using namespace std;
template<typename T> class base
{
public:
template<bool good> void foo()
{
cout << "base::foo<" << boolalpha << good << ">()" << endl;
}
};
template<typename T> class derived : public base<T>
{
public:
using ????
void bar()
{
foo<true>();
}
};
Just for the record, even though it does not provide any answer or workaround, but I am currently working with VS Express 2013, and I can assure you that
#include <iostream>
template<typename T> class base
{
public:
template<bool good> void foo()
{
std::cout << "base::foo<" << good << ">()" << std::endl;
}
};
template<typename T> class derived : public base<T>
{
public:
void bar()
{
foo<true>();
}
};
struct A{};
void main() {
derived<A> a;
a.bar();
}
works perfectly fine...

Template specialization and inheritance

Suppose I have a template class with a lot of functions and I want to specialize them to change only a few of them and keep the other ones exactly as specified in the base template class.
How can I do that?
Below is what I want to achieve, but the solution isn't good, because it does not allow me to refer to the specialization for int as Base<int> – I need to use IntSpec for that.
#include <iostream>
using namespace std;
template<typename T>
struct Base
{
void print1() {cout << "Base::print1" << endl;};
void print2() {cout << "Base::print2" << endl;};
};
struct IntSpec : public Base<int>
{
void print2() {cout << "Base<int>::print2()" << endl;};
};
int main()
{
Base<double> d;
// Base<int> i; <-- I want this kind of instantiation
IntSpec i;
d.print1();
d.print2();
i.print1();
i.print2();
}
The output is:
Base::print1
Base::print2
Base::print1
Base<int>::print2()
Nicol's solution works fine, but this is an alternative:
template<typename T>
struct Base
{
void print1() {cout << "Base::print1" << endl;};
void print2() {cout << "Base::print2" << endl;};
};
template<>
void Base<int>::print2() {cout << "Base<int>::print2()" << endl;};
That way you can specialize only specific member functions and still use those that you haven't specialized(in this case, print1) without any problem. So now you'd use it just like you wanted:
Base<int> i;
i.print1();
i.print2(); // calls your specialization
Demo here.
You just have to use two template classes:
template<typename T>
struct CommonBase
{
void print1() {cout << "Base::print1" << endl;};
void print2() {cout << "Base::print2" << endl;};
};
template<typename T>
struct Base : public CommonBase<T>
{
};
template<>
struct Base<int> : public CommonBase<int>
{
void print2() {cout << "Base::print2" << endl;};
};
You always use Base, rather than CommonBase.
Another solution would be to add a level of indirection in the function you want to redefine, i.e.
template<typename T>
struct foo
{
template<typename T2>
void bar_impl()
{
//generic function
}
void bar()
{
bar_impl<T>();
}
};
Then you can specialize each function individually for each type or specialize the whole type as wanted.