Using directive and Partial Specialization - c++

I have a templatized interface class, with a couple of implemented methods and a couple of virtual ones.
I need to specialize it in order to modify the signature of some methods, but others would remain the same.
Is there a way to bring the methods that remain the same back from the original template, either via using directive, by directly calling back to them or in another way, or I must copy/paste every single method back into the specialization?
template <typename T>
struct X {
void faa(T t) const { std::cout << t << '\n'; }
void foo() const { std::cout << "foo\n"; }
};
template <>
struct X<void> {
void faa() const { std::cout << "none\n"; }
// Something along these lines
// using X<T>::foo;
// void foo() const { X<T>::foo(); }
};

Seems so. You can't get the functions in X with different signatures using using directives. There is a better workaround than copying everything from the template to the specialization. You can use a "common base class".
template <typename T>
struct X_base {
void foo() const { std::cout << "foo\n"; }
};
template <typename T>
struct X : public X_base<T> {
void faa(T t) const { std::cout << t << '\n'; }
};
template <>
struct X<void> : public X_base<void> {
void faa() const { std::cout << "none\n"; }
};
In this way, X<void>::foo acts just like X_base<void>::foo, while X<T>::faa and X<void>::faa do not interfere with each other.

Related

how to add member-variable for a specialized version of a template class?

I have a template class, and at least 95% codes of it is same for all types of the template-parameter, unless a member-variable and a function should be added for one specialization.
The sample I want to get is following:
template <typename T>
class AClass {
private:
T payLoad;
public:
AClass( const T& crp_payload ) : payLoad( crp_payload ) {};
void showMe() {
cout << "Common showMe:" << payLoad << endl;
};
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
// specializing for int ----------------------------
// dedicated function
template <int>
void showPayload() {
cout << "AClass<int>::showPayload:" << payLoad << endl;
};
// dedicated variable, but following code can not be compiled!
template <int>
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
};
My questions:
How to add merely "otherPayload" variable without re-coding entire
AClass<int>?
How to call showPayload() sinc I get a error msg when I
do it in main() as above.
Is there no way only by specializing to "revise/supplement" some
members to a class without totally re-implement it?
One possible way would be the good old inheritance:
template<class T> struct Extra {};
template<> struct Extra<int> {
int extraPayload;
void showPayload();
};
template<class T> class Class: public Extra<T> {
void showMe();
};
template<> void Class<int>::showMe() { showPayload(); }
All the specialization-specific parts are extracted in a separate class, and common methods are specialized as needed.
I think you can simply do normal specialization of the template-class:
#include <iostream>
#include <iomanip>
template <typename T>
class BaseClass
{
protected:
T payLoad;
public:
BaseClass(const T& crp_payload)
: payLoad( crp_payload )
{ }
void showMe() {
std::cout << "Common showMe:" << payLoad << std::endl;
}
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
};
template <typename T>
class AClass
: public BaseClass<T>
{
public:
AClass( const T& crp_payload )
: BaseClass<T>(crp_payload)
{ }
};
// specializing for int ----------------------------
template<>
class AClass<int>
: public BaseClass<int>
{
public:
AClass( int crp_payload )
: BaseClass(crp_payload)
{ }
// dedicated function
void showPayload() {
std::cout << "AClass<int>::showPayload:" << payLoad << std::endl;
}
private:
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
}

C++ templates and function resolution

Here is a problem I stumbled accross when refactoring some code and I was wondering if there is a better way to do it:
#include <iostream>
template<typename T>
class Foo
{
public:
Foo()
{
init(x);
}
T x;
};
void init(int& i)
{
i = 42;
}
int main()
{
Foo<int> foo;
std::cout << foo.x << std::endl;
return 0;
}
Unfortunately, this doesn't compile - neither with GCC or with Clang. The function init called in Foo's constructor is not declared. In this toy example, this could be solved by moving the function itself ahead of the template. However, in a more complex context, this may not work. Originally, I intended to use overloads of init to allow some setup for the classes used in the template.
I assumee that in this context init is a non-dependend name - even though the argument of the function call depends on the template parameter (which was odd for me at first). Is there a way to trick it to also consider function definitions defined after the template itself?
I know that I can use template specialization (which was in the original code in the first place, but I wanted to replace it with simpler overloads):
template<typename>
struct Initializer;
template<>
struct Initializer<int>
{
static void init(int& i)
{
i = 42;
}
}
Is there a way to make this work with function overloads as well? I know, boost::serialization also relies on function overloads for custom types, but I did not really find where and how they implemented that.
You can solve the ordering problem by calling through a template function object - in the same way that boost::hash finds the ADL-function hash_value(x).
This works because the expansion of the template is deferred until the point of first use:
#include <iostream>
namespace A {
struct XX {
friend void init(XX&);
};
}
namespace B {
struct YY {
friend void init(YY&);
};
}
/// default case - call init on T found by ADL
template<class T>
struct call_init
{
void operator()(T& o) const {
init(o);
}
};
template<typename T>
class Foo
{
public:
Foo()
{
auto initialiser = call_init<decltype(this->x)>();
initialiser(this->x);
}
T x;
};
void init(int& x) {
x = 2;
}
// special case, initialise an int
template<> struct call_init<int>
{
void operator()(int& x) const {
init(x);
}
};
int main()
{
Foo<int> foo;
Foo<A::XX> foox;
Foo<B::YY> fooy;
std::cout << foo.x << std::endl;
return 0;
}
Your problem is also that intis not a class and no ADL is done for it, replacing int by custom class works:
template<typename T>
class Foo
{
public:
Foo() { init(x); }
T x;
};
struct C
{
int i = 0;
};
void init(C& c) { c.i = 42; }
Demo.
To allow to works for primitive type as int, you have to introduce some custom type:
template <typename> struct tag {};
template<typename T>
class Foo
{
public:
Foo() { init(x, tag<T>{}); }
T x;
};
void init(int& i, tag<int>) { i = 42; }
Demo

Dynamic dispatch in C++ - better syntax

I want to have a dynamic_call functionality in C++. It should trigger overload resolution and call the most specific function on the target class (Visitor) depending on the dynamic type of the argument. It should replace the visitor pattern and should work like the dynamic keyword in C#.
I pasted what I got so far below. I want to not have to declare the generic lambda on caller side but on the implementation of dynamic call to make it easier to use. Is this possible?
#include <iostream>
struct Base { virtual ~Base() = default; };
class A : public Base {};
class B : public Base {};
template <class... Ts>
class dynamic_call {
public:
template <class F, class Arg>
static void call(F& func, Arg& a) {
call_impl<F, Arg, Ts...>(func, a);
}
private:
template <class F, class Arg>
static void call_impl(F& /*func*/, Arg& /*a*/) {
//end of recursion => nothing more to be done
}
template <class F, class Arg, class T, class... R>
static void call_impl(F& func, Arg& a) {
T* t = dynamic_cast<T*>(&a);
if(t) {
func(*t);
}
call_impl<F, Arg, R...>(func, a);
}
};
using namespace std;
struct Visitor {
void Visit(A&) { cout << "visited for a" << endl; }
void Visit(B&) { cout << "visited for b" << endl; }
};
int main(int /*argc*/, char */*argv*/[])
{
Visitor v;
auto func = [&v](auto& a) { v.Visit(a); };
A a;
dynamic_call<A, B>::call(func, a);
B b;
dynamic_call<A, B>::call(func, b);
{
Base& base(a);
dynamic_call<A, B>::call(func, base);
}
{
Base& base(b);
dynamic_call<A, B>::call(func, base);
}
return 0;
}
I want to call it like this without the need to add the generic lambda.
dynamic_call<A,B>::call(v, a);
Here are some ideas, I am not sure what your requirements are, so they might not fit:
Change Visit into operator(). Then the call syntax reduces to dynamic_call<A,B>::call(v, a); as you required. Of course that is only possible if the interface of the visitor may be changed.
Change func(*t) in call_impl to func.Visit(*t). Then again the caller can use dynamic_call<A,B>::call(v, a); and no change to the interface of the visitor is necessary. However every visitor used with dynamic_call now needs to define Visit as visitor method. I think operator() is cleaner and follows the usual patterns, e.g. for Predicates in the standard library more.
I don't particularly like either of these because the caller always has to know the possible overloads available in the visitor and has to remember using dynamic_call. So I propose to solve everything in the visitor struct:
struct Visitor {
void Visit(A&) {
cout << "visited for a" << endl;
}
void Visit(B&) {
cout << "visited for b" << endl;
}
void Visit(Base& x) {
dynamic_call<A,B>::call([this](auto& x){Visit(x);}, x);
}
};
This can be called with v.Visit(a), v.Visit(b) and v.Visit(base). This way the user of Visitor does not need to know anything about the varying behavior for different derived classes.
If you do not want to modify Visitor, then you can just add the overload via inheritance:
struct DynamicVisitor : Visitor {
void Visit(Base& x) {
dynamic_call<A,B>::call([this](auto& x){Visit(x);}, x);
}
};
The points can be combined, for example into:
struct Visitor {
void operator()(A&) {
cout << "visited for a" << endl;
}
void operator()(B&) {
cout << "visited for b" << endl;
}
void operator()(Base& x) {
dynamic_call<A,B>::call(*this, x);
}
};
Used as v(a), v(b) and v(base).

How to call function in derived if exists else use a default if using CRTP?

I have a helper base class for certain structs that uses CRTP to help me get some information about them:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
};
I already have structs using this defined in various libraries in my code base, and I would like to have a way to log them. My first idea was something like this:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
virtual void print(std::ostream& out) const { out << "(" << sizeof(T) << ")"; }
};
but then I realized that wouldn't work for a couple reasons - one of them being adding virtual actually changes the size beyond just the POD data.
Is there a way, without the virtual keyword, for me to have a default toStr method which uses the above implementation unless the particular derived class T has an implementation in which case it defers to that?
I think the most straightforward way to do something like this is to dispatch to a different non-virtual function that the derived class can shadow if it so desires. For example:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
void print(std::ostream &out) const {
// Cast to derived, call do_print. This will be derived's do_print
// if it exists and MyHelper's otherwise.
static_cast<T const*>(this)->do_print(out);
}
void do_print(std::ostream& out) const {
out << "(" << sizeof(T) << ")";
}
};
struct A : MyHelper<A> {
// no do_print, so MyHelper<A>'s will be used
int x;
};
struct B : MyHelper<B> {
// B's do_print is found and used in MyHelper<B>::print
void do_print(std::ostream &out) const {
out << "Hello!\n";
}
};
template<typename T>
void foo(MyHelper<T> const &r) {
r.print(std::cout);
}
int main() {
A a;
B b;
foo(a);
foo(b);
}
Output:
(4)Hello!
You could probably also build something with SFINAE that doesn't need a second member function, but I doubt the added complexity would be worth it.

C++ - Recover Template or cast to Template

Consider the following code listing:
#include <iostream>
#include <typeinfo>
class Interface { };
template<typename T>
class Class : public Interface { };
template<typename T>
Interface *producer() {
std::cout << "produced " << typeid(T).name();
return new Class<T>();
}
template<typename T>
void consumer(Class<T> *class_value) {
std::cout << "consumed " << typeid(T).name();
}
void mediator(Interface *value) {
/* The magic happens here */
consumer(class_value);
}
int main() {
Interface *value = producer<int>();
mediator(value);
}
Is there any possible way to call the 'consumer' template function from the 'mediator' function?
If you changed your design a little, you could make the derived class do the work:
class Interface
{
virtual void consume() = 0;
virtual ~Interface() {}
};
void mediator(Interface * value)
{
value->consume();
}
template <typename T>
void consumer(Class<T> * class_value)
{
std::cout << "consumed " << typeid(T).name();
}
template <typename T> class Class : public Interface
{
virtual void consume() override
{
consumer<Class>(this);
}
// ...
};
The direct answer
It looks like the code you post has been written to illicit the use of a cast and adding a suitable case seems the direct answer.
void mediator(Interface *value) {
/* The magic happens here */
Class<int> *class_value(static_cast<Class<int> *>(value));
consumer(class_value);
}
In this case since it's known that only the int version will arrive we can use a static_cast.
Doesn't scale
However this approach does not scale well if Class is specialized for more types.
For example to have mediator handle float as well you would need to try each of the types:
void mediator(Interface *value) {
/* The magic happens here */
{
Class<int> *class_value(dynamic_cast<Class<int> *>(value));
if(class_value) {
consumer(class_value);
return;
}
}
{
Class<float> *class_value(dynamic_cast<Class<float> *>(value));
if(class_value) {
consumer(class_value);
return;
}
}
}
Double dispatch
Changing the design as Kerrek SB suggests to use double dispatch gives a much cleaner and scalable solution.
You can use dynamic_cast:
consumer(dynamic_cast<producer<int>&>(value));