I have created a class either<l, r> much like Haskell's Either a b. I have also implemented a function map directly in the class; this is what the code looks like:
template<typename l, typename r>
class either
{
template<typename b>
either<l, b> map(const std::function<b (r)> &f)
{
// ...
}
};
Now I want to isolate the map function in order to create an abstract base class called functor
template<typename a, template <a> class derived>
class functor
{
public:
virtual ~functor();
template<typename b>
derived<b> map(const std::function<b (a)> &f) = nullptr;
};
either would inherit this class:
class either : functor<r, either<l, r>>
however this is invalid C++ as template member functions can not be virtual.
Moreover, I have attempted to test if <r, either<l, r>> can match <a, derived<a>> in functor<r, either<l, r>> (or any other template for that matter) but haven't been able to since it has two template parameters. Also note that other derived classes of functor might have different numbers of template arguments that are irrelevant to functor.
Can the functor base class be expressed in C++ templates?
Since you are using the curiously recurring template pattern, there's no need for virtual functions. Your goal of dispatching to the method of the derived class can be achieved directly from the base class.
A typical implementation would be the following :
#include <iostream>
#include <functional>
using namespace std;
template<typename a, class derived>
class functor
{
public:
// You have to define the destructor
virtual ~functor() {}
template<typename b>
// The full type of the derived class is known
derived map(const std::function<b(a)> &f)
{
// Here you take advantage of the CRTP
return static_cast<derived*>(this)->map(f);
}
};
template<typename l, typename r>
// You have to put public as inheritance access level
class either : public functor<r, either<l, r>>
{ // The way you want to inherit implies that the base has no
// template template parameter, just template parameters !!
public:
template<typename b>
either<l, b> map(const std::function<b(r)> &f)
{
cout << "In derived" << endl;
return either<l, b>();
}
};
int main()
{
// pointer to base class points to a derived object
functor<int, either<int, int>> *ff = new either<int, int>();
// map function will call the method of the derived class
ff->map<int>([](int k){ return 1; });
return 0;
}
I took the liberty of pointing some things out in the comments. HTH
Related
I wanted do design a template class with two arguments that at compile time inherited based on the template arguments one of two mutually exclusive base classes.
I wanted to keep it simple for me so came up with this working example. The inheritance condition i got with std::conditional based on the template arguments. The specialized methods for that conditional inheritance I set with std::enable_if.
class Empty {};
template<typename T>
class NonEmpty { protected: std::vector<T> mObjects; };
template< typename A, typename B = A>
class Storage : public std::conditional<std::is_same<A, B>::value, Empty, NonEmpty<B>>::type
{
public:
template<typename C = B, typename std::enable_if<std::is_same<C, A>::value>::type* = nullptr>
void doStuff()
{
// one argument or two arguments with same type
// do stuff ...
};
template<typename C = B, typename std::enable_if<std::is_same<C, A>::value>::type* = nullptr>
void doSomthingElse()
{
// one argument or two arguments with same type
// do something exclusively just for this argument constellation ...
};
template<typename C = B, typename std::enable_if<!std::is_same<C, A>::value>::type* = nullptr>
void doStuff()
{
// two arguments with different types
// do stuff with inherited variables of NonEmpty-Class ...
};
};
int main()
{
EmptyClass<int> emp;
NonEmptyClass<int, float> nonemp;
emp.doStuff();
emp.doSomethingElse();
nonemp.doStuff();
}
Is there a better way to go about it, or are there any improvements for my existing solution?
(I am using GCC 8.1.0 with C++ 14)
In my opinion you're much better of partially specializing the template, since the entire implementation for both versions are completely independent. This way you can also not inherit any class instead of inheriting an empty class.
template<typename T>
class NonEmpty {
protected:
std::vector<T> mObjects;
};
template<typename A, typename B = A>
class Storage : public NonEmpty<B>
{
public:
void doStuff()
{
std::cout << "doStuff() different types\n";
};
};
template<typename A>
class Storage<A, A>
{
public:
void doStuff()
{
std::cout << "doStuff() same types\n";
};
void doSomethingElse()
{
std::cout << "doSomethingElse()\n";
};
};
int main() {
Storage<int> emp;
Storage<int, float> nonemp;
emp.doStuff();
emp.doSomethingElse();
nonemp.doStuff();
}
I do not see the benefit of placing it all in one template. I have the impression that you are making things complicated by stuffing all in a single template but then need to select which version it is for each single method. Two seperate classes:
template <typename A>
struct inherits_from_empty : Empty {
// implement methods here, no sfinae needed
};
and
template <typename A, typename B>
struct inherits_from_nonEmpty : NonEmpty<A> {
// implement methods here, no sfinae needed
};
Can be choosen from via
template <typename A,typename B>
using Storage = std::conditional_t<std::is_same<A, B>::value,
inherits_from_empty<A>,
inherits_from_nonEmpty<A>>;
This is a continuation of the following SO question c++11 get type of first (second, etc...) argument, similar to result_of.
I need to get the type of the (first) argument of a class function. The additional problem is that the function is overloaded, and that the argument type may be a (pointer to) a base class of a known type. I first need to disambiguate the call using this second, known, type. See code example.
class Abase {
public:
void fun2() {
// Success!
}
};
class C {void fun2() {};};
class A1 : public Abase {};
class A2 : public Abase {};
class A : public A1, public A2 {};
class B {
public:
void fun1(A1* t) {}
void fun1(C* t) {}
};
template <typename T1,typename T2>
void problematic(T1* a, T2* b)
{
//This is ambiguous due to inheritance
a->fun2();
// I want to achieve this
static_cast<A1*>(a)->fun2();
// Based on type of first argument of (the overloaded) fun1 actually being called
b->fun1(a);
static_cast</*INSERT METAPROGRAMMING HERE*/>(a)->fun2();
}
int main()
{
A a;
B b;
problematic(&a, &b);
}
The following would have solved the problem if not for the overloaded fun1
template<class T>
// Does not work. fun1 is ambiguous due to overloaded function
struct function_traits : function_traits<decltype(&T::fun1)> {
};
template<class T, class... Args>
struct function_traits<void(T::*)(Args...)> {
using argument_types = std::tuple<Args...>;
};
template<class T>
using first_argument_type = typename std::tuple_element<0, typename function_traits<T>::argument_types>::type;
// ...
// :-(
static_cast<first_argument_type<T2>>(a)->fun2();
I asked the following question in this post (pasted below for convenience). One of the comments suggested that there is a CRTP-based solution to the problem. I am not able to figure out how CRTP is relevant here (well, I never used CRTP before, so I am not used to thinking in these terms). So, how would a CRTP-based solution look like?
Here is the cited question:
Is it possible to write a template function that would possess type information about the base class of the template argument? (assuming that the template argument derives from one class only)
So, I am looking for something like this:
template <class T>
auto f(T t) -> decltype(...) { // ... is some SFINAE magic that
// catches B, the base of T
std::cout << (B)t << std::endl;
}
Some relevant background: I am writing a generic implementation of the A* algorithm. The template argument is a Node structure. So, the user might define:
struct NodeBase {
REFLECTABLE((double)g, (double)f)
// Using the REFLECTABLE macro as described here:
// https://stackoverflow.com/a/11744832/2725810
};
struct NodeData : public NodeBase {
using Base1 = NodeBase;
REFLECTABLE((double)F)
};
I would like to write a function that prints the contents of the node structure. REFLECTABLE does all the hard work of extracting the fields of the struct. However, when the user gives me a NodeData instance, my function needs to print the contents of the NodeBase component as well. I would like to later add overloads of my function for two and three base classes.
to know whether a class derives from a base class we have the std::is_base_of<> template structure, which can be used in conjunction with partial specialisation, or std::enable_if.
Here is a demonstration of using a partially specialised structure to apply a an operation depending on whether it's derived from node_base or not (in this case, it just prints the base object but you could do any other operation)
#include <iostream>
#include <type_traits>
// base class
struct node_base
{
};
std::ostream& operator<<(std::ostream& os, const node_base& nb)
{
os << "node_base_stuff";
return os;
}
// a class derived from node_base
struct node : public node_base
{
};
// a class not derived from node_base
struct not_node
{
};
// apply the general case - do nothing
template<class T, class = void>
struct report_impl
{
static void apply(const T&) {};
};
// apply the case where an object T is derived from node_base
template<class T>
struct report_impl<T, std::enable_if_t< std::is_base_of<node_base, T>::value > >
{
static void apply(const T& t) {
std::cout << static_cast<const node_base&>(t) << std::endl;
};
};
// the general form of the report function defers to the partially
// specialised application class
template<class T>
void report(const T& t)
{
report_impl<T>::apply(t);
}
using namespace std;
// a quick test
auto main() -> int
{
node n;
not_node nn;
report(n);
report(nn);
return 0;
}
expected output:
node_base_stuff
Here is my own first solution. It is not CRTP though and it suffers from a huge drawback as explained at the end of the answer:
template <class Base1_ = void, class Base2_ = void, class Base3_ = void,
class Base4_ = void>
struct ManagedNode;
// For classes that do not derive
template <> struct ManagedNode<void, void, void, void> {
using Base1 = void; using Base2 = void; using Base3 = void;
using Base4 = void;
};
// To avoid inaccessible base
// See http://stackoverflow.com/q/34255802/2725810
struct Inter0: public ManagedNode<>{};
// For classes that derive from a single base class
template <class Base1_>
struct ManagedNode<Base1_, void, void, void> : public Inter0,
public Base1_ {
using Base1 = Base1_;
};
// To avoid inaccessible base
template <class Base1_>
struct Inter1: public ManagedNode<Base1_>{};
// For classes that derive from two base classes
template <class Base1_, class Base2_>
struct ManagedNode<Base1_, Base2_, void, void> : public Inter1<Base1_>,
public Base2_ {
using Base2 = Base2_;
};
// Some user classes for testing the concept
struct A : public ManagedNode<> {
int data1;
};
struct B : public ManagedNode<> {};
struct C : public ManagedNode<A, B> {};
int main() {
C c;
std::cout << sizeof(c) << std::endl;
return 0;
}
This code produces the output of 12, which means that c contains the data1 member three times! For my purposes this drawback over-weighs the benefits of the reflection that this approach provides. So, does anyone have a suggestion for a better approach?
Given two templated classes which are very similar but behave differently:
template<class T>
firstBase {};
template<class T>
secondBase {};
Now I've got this other class, which, based on it's template parameter, will derive either from firstBase or from secondBase:
template<class B, class T>
myClass : public B<T> { /* T is used in here */ };
Well, that does not work. The compiler tells me that B is an unknown template name. (error: unknown template name 'B')
My current workaround is to define myClass as
template<class B, class T>
myClass : public B { /* T is used in here */ };
and the caller of myClass needs to intatiate it via myClass<b<t>, t> instead of myClass<b, t>.
The latter would be really nice and reduce some copy&paste code. Is there any other way of achieving this?
In my use case I'm trying to implement a deep_const_ptr for the pimpl idiom enabling 'true constness'. Depending on whether myClass needs to be copy-assignable or not, it either uses deep_const_ptr<std::shared_ptr> or deep_const_ptr<std::unique_ptr> for its private pointer.
#include <memory>
#include <iostream>
template<class pointerT, class typeT>
class deep_const_ptr : public pointerT
{
public:
explicit deep_const_ptr(typeT* ptr) : pointerT(ptr) { }
// overloading pointerT::operator->() for non-constant access
typeT* operator->() {
std::cout << "deep_const_ptr::operator->()" << std::endl;
return pointerT::operator->();
}
// overloading pointerT::operator->() for constant access
const typeT* operator->() const {
std::cout << "deep_const_ptr::operator->() const" << std::endl;
return pointerT::operator->();
}
};
Edit
So I ended up, as suggested by Luc Danton in his answer, passing std::unique_ptr<myClass::Private> or std::shared_ptr<myClass::Private> to my custom deep_const_ptr:
template<typename pointerTypeT>
class deep_const_ptr : public pointerTypeT {
explicit deep_const_ptr(typename pointerTypeT::element_type* ptr) : pointerTypeT(ptr);
typename pointerTypeT::element_type* operator->();
const typename pointerTypeT::element_type* operator->() const;
};
deep_const_ptr<std::unique_ptr<Test::Private>> d_unique;
deep_const_ptr<std::shared_ptr<Test::Private>> d_shared;
What you want is template template parameter:
// vvvvvvvvvvvvvvvvvv
template<template<typename> class B, class T>
class myClass : public B<T> { /* T is used in here */ };
Then, use that like:
myClass<firstBase,int> myIntClassObject;
myClass<secondBase,bool> myBoolClassObject;
For std::unique_ptr, you can make a wrapper:
template<typename T>
class uniquePtr : public std::unique_ptr<T>
{
};
or
template<typename T>
using uniquePtr = std::unique_ptr<T>;
I recommend against template template parameters in general. For instance std::unique_ptr and std::shared_ptr are different in that the former accepts two type parameters and the latter just one. So if you declare e.g. template<template<typename> class B, typename T> class foo; then foo<std::shared_ptr, int> is valid but foo<std::unique_ptr, int> isn't.
In your particular case you could use template<typename...> class B as a parameter, because that kind of template template parameters is special. Still, this would only accept templates that only take type parameters (not even template template parameters). Sometimes this can be worked around with alias templates, sometimes it can't.
In my experience there are better alternatives -- for instance you can conditionally inherit:
template<typename T>
struct pointer: std::conditional</* Make a choice here*/, std::unique_ptr<T>, std::shared_ptr<T>>::type {};
Or why not just accept the smart pointer as the parameter itself:
template<typename Pointer>
struct foo {
Pointer pointer;
/* typename Pointer::element_type plays the role that T used to have */
};
The Standard Library itself takes some steps to avoid template template parameters: have you ever noticed that an std::vector<T> uses std::allocator<T> as an argument, and not std::allocator? As a tradeoff, it means that an Allocator must provide a rebind member alias template.
B should be a template template parameter:
template<template <class> class B, class T>
class myClass : public B<T> { /* T is used in here */ };
Now you can give either firstBase or secondBase as the first template argument because they are templates.
You simply need to use a template-template parameter to get it to work:
template <
template <class> class B, class T>
// ^^^^^^^^^^^^^^^^
class myClass : public B<T> { / ... / };
It seems what you need is template template parameters:
template<template<class> class B, class T>
// ^^^^^^^^^^^^^^^
class myClass : public B<T> { /* T is used in here */ };
Now the first template argument for the myClass class template must be itself a class template that accepts one template (type) parameter. So, putting everything together:
template<class T>
class firstBase {};
template<class T>
class secondBase {};
template<template<class> class B, class T>
class myClass : public B<T> { /* T is used in here */ };
And here is how you would instantiate your myclass template to create a class that derives from firstBase<int>:
myClass<firstBase, int> obj;
Finally, here is a live example.
Is there a partial specialization for template class method?
template <class A, class B>
class C
{
void foo();
}
it doesn't work to specialize it like this:
template <class A> void C<A, CObject>::foo() {};
Any help?
If you are already have specialized class you could give different implementation of foo in specialized class:
template<typename A, typename B>
class C
{
public:
void foo() { cout << "default" << endl; };
};
template<typename A>
class C<A, CObject>
{
public:
void foo() { cout << "CObject" << endl; };
};
To specialize member function in Visual C++ 2008 you could make it template too:
template<typename A, typename B>
class C
{
template<typename T>
void foo();
template<>
void foo<CObject>();
};
The solution above seems to will be available only in future C++ Standard (according to draft n2914 14.6.5.3/2).
I think there is a misunderstanding there.
There are two kinds of templates:
the template classes
the template methods
In your example, you have a template class, which of course contains some methods. In this case, you will have to specialize the class.
template <class A>
class C<A,CObject>
{
void foo() { ... } // specialized code
};
The problem in your example is relatively simple: you define the method foo for the specialization C but this specialization has never been declared beforehand.
The problem here is that you have to fully specialize your C class (and thus copying a lot of data). There are a number of workarounds.
Inheritance (Composition ?): do all the common work in a base class, then have the C class inherits and specialize as appropriate
Friend: instead of having the 'foo' method being a member of C, define it as a friend free functions and specialize only this method
Delegation: have your 'foo' method call another method 'bar', which is a free function, and specialize 'bar' appropriately
Which in code gives:
// 1- Inheritance
template <class A, class B>
class CBase
{
// Everything that does not require specialization
};
template <class A, class B>
class C: public CBase<A,B>
// depending on your need, consider using another inheritance
// or even better, composition
{
void foo(); // generic
};
template <class A>
class C<A,CObject> : public CBase<A,CObject>
{
void foo(); // specialized
};
// 2- Friend
// note the change in signature:
// - now you need to pass the attributes to be changed
// - the last parameter helps differentiating the overload
// as there is no specialization for functions
template <class A, class B> void foo(Arg1&, Arg2&, const B&);
template <class A> void foo(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
friend template <class, class> foo;
};
// 3- Delegation
// same signature as foo in (2)
template <class A, class B> void bar(Arg1&, Arg2&, const B&);
template <class A> void bar(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
void foo() { bar(member1, member2, B()); }
};
Hope it clarifies, and helps!
No, there is no partial function template specialization in C++0x to be added.
As correctly mentioned above, with regards to function templates basically 2 things were done:
default template arguments were made available;
variadic templates were introduced.
So as before, workarounds should be used to "emulate" partial function templates specialization.
Since the class is the template, you need to specialize that:
template <class A>
class C<A, CObject>
{
void foo() { ... }
}
If I remember correctly, you cannot make partial template specialization for functions. Not sure whether it is included in C++0X
Update:
(Awaiting confirmation) As noted in the comments, partial template specialization of functions is possible in C++0X.
A method template may delegate to (static) methods of partially specialized classes or structs. Template parameters in the outer class are not helpful for answering the question.
class ClassWithSpecializedMethodEmulation
{
private:
template <typename A, typename B> struct Calculator;
public:
template <typename A, typename B> A evaluate(A a, B b)
{
return Calculator<A,B>::evaluate(a,b);
}
private:
template <typename A, typename B> struct Calculator
{
// Common case: multiply
static A evaluate(A a, B b)
{
return (A)(a*b);
}
};
// with double argument a do something else
template <typename B> struct Calculator<double, B>
{
static double evaluate(double a, B b)
{
return (double)(a - b);
}
};
};
In case the method requires access to class members, struct Calculator additionally must be friend of ClassWithSpecializedMethodEmulation and get a this-pointer passed.