class Foo1: public IFoo
{
public:
template <class T>
std::vector<T> foo()
{
return std::vector<T>();
}
};
class Foo2: public IFoo
{
public:
template <class T>
std::vector<T> foo()
{
return std::vector<T>();
}
};
How can I define a common interface class for the two implementations above, such that std::vector<T> foo() is defined for this interface? Ignore that the implementations of the functions are identical.
UPDATE:
I'm writing a Container class which represents data which is sent to me via a C api.
An instance of my Container will store data of a given type, such as Container<int>, Container<std::string> and Container<Foo>.
The C api returns the data in a very awkward manner and it is possible that this will change in the future. It is possible that I can copy the data into for example std::list or std::vector, but since so much data is passed from the C api it is not known yet if this will be OK or not.
For this reason, the Container class should be independent of how the data is actually stored. I achieve this using Getter and Setter classes which I pass into the contructor, as follows:
Container<int>(Getter1<int>(uglyCApiContainer),Setter1<int>(uglyCApiContainer));
Therefore if I abandon Getter1 and Getter2 which deals with how the C api stores data, I will only need to change the creation of Containers.
However, I have a problem with this design. The type Foo.
Foo is a complex type which contains itself a set of Containers. At the moment it looks something like this:
class Foo
{
public:
...
template <class V>
Container<V> getMember(std::string& memberName)
};
So a given Foo can have a set of containers of different types. The types of these members are know to me in advance since they are stored in a model. Foo is currently a wrapper around the ugly C api memory implementation, but I would like to separate also for Foo the memory representation as I've done for the Container.
I'm not sure how to make Foo free of its memory implementation. One idea I had was to make getMember virtual so as to introduce perhaps different implementations but this isnt possible for templated functions.
Here's a solution using tag dispatching and virtual inheritance:
#include <vector>
template<typename T> struct tag {};
template<typename T> class IFooImpl {
public:
virtual std::vector<T> getImpl(tag<T>) = 0;
};
class IFoo: public virtual IFooImpl<char>, virtual IFooImpl<int>
{
public:
template<typename T> std::vector<T> get() {
return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
}
};
template<typename T>
class FooImpl: public virtual IFooImpl<T> {
public:
std::vector<T> getImpl(tag<T>) { return {}; }
};
class Foo: public IFoo, FooImpl<char>, FooImpl<int> {
};
int main() {
Foo().get<char>();
}
There's a little bit of repetition where the supported types are covered (here char and int), but that can be avoided with variadic template inheritance:
#include <vector>
template<typename T> struct tag {};
template<template<typename> class C, typename... Types> class Inherit {};
template<template<typename> class C, typename T, typename... Rest>
class Inherit<C, T, Rest...>: public C<T>, Inherit<C, Rest...> {};
template<typename T> class IFooImplV {
public:
virtual std::vector<T> getImpl(tag<T>) = 0;
};
template<typename T> class IFooImpl: public virtual IFooImplV<T> {};
template<typename... Types> class IFoo: public Inherit<IFooImpl, Types...> {
public:
template<typename T> std::vector<T> get() {
return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
}
};
template<typename T> class FooImpl: public IFooImpl<T> {
public:
std::vector<T> getImpl(tag<T>) { return {}; }
};
template<typename... Types> class FooMulti:
public IFoo<Types...>, Inherit<FooImpl, Types...> {};
class Foo: public FooMulti<char, int> {};
int main() {
Foo().get<char>();
}
Related
I have generated a simpler example of what I am trying to accomplish. I would like to be able to call a function, which returns a class containing two template parameters, based on one of the two templated parameters (Variance).
My hierarchy can be simplified to this.
template<typename T>
class AbstractType {};
template<typename T, Variance Type>
class BaseType : public AbstractType<T> {};
template<typename T, Variance Type>
class FinalType : public BaseType<T, Type>{};
Where FinalType in this example isn't strictly necessary, it also inherits from other templated classes in my actual code, which serves no purpose in this example, so it's been removed.
Here's the example code.
enum class Variance {
Interval,
Weighted,
Constant
};
template<typename T>
class AbstractType
{
protected:
AbstractType(T* _Instance) :
Instance(_Instance) {};
T* Instance;
};
template<typename T, Variance Type>
class BaseType : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
};
template<typename T>
class BaseType<T, Variance::Interval> : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
int Interval;
public:
void SetInterval(int NewInterval) { Interval = NewInterval; }
};
template<typename T>
class BaseType<T, Variance::Weighted> : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
int Weight;
public:
void SetWeight(int NewWeight) { Weight = NewWeight; }
};
template<typename T, Variance Type>
class FinalType : public BaseType<T, Type>
{
public:
FinalType(T* _Instance) :
BaseType<T, Type>(_Instance)
{};
};
struct Interface
{
template<typename T>
BaseType<T, Variance::Weighted>* CreateBaseInstance(T t, int Weight) {
FinalType<T, Variance::Weighted>* OutObj = new FinalType<T, Variance::Weighted>(t);
OutObj.SetWeight(Weight);
return OutObj;
}
template<typename T>
BaseType <T, Variance::Interval>* CreateBaseInstance(T t, int Interval) {
FinalType<T, Variance::Weighted>* OutObj = new FinalType<T, Variance::Interval>(t);
OutObj.SetInterval(20);
return OutObj;
}
};
struct Object {};
void test()
{
Interface Inter;
Object Obj;
Inter.CreateBaseInstance<Object, Variance::Weighted>(Obj, 50); // Too many template arguments
Inter.CreateBaseInstance<Object, Variance::Interval>(Obj, 10); // Too many template arguments
Inter.CreateBaseInstance<Object>(Obj, 50); // More than one instance of overloaded function
Inter.CreateBaseInstance<Object>(Obj, 10); // More than one instance of overloaded function
}
Additionally, Object being used as the first template is just for testing purposes. I will not know the type in this codebase.
I've been able to resolve this problem by creating multiple functions such as..
template<typename T>
BaseType<T, Variance::Interval>* CreateIntervalInstance(T t, int Interval)…
template<typename T>
BaseType<T, Variance::Weighted>* CreateWeightedInstance(T t, int Weight)…
template<typename T>
BaseType<T, Variance::Constant>* CreateConstantInstance(T t)…
However, as mentioned earlier, FinalType inherits from another set of classes, so while the above works, it becomes crowded and unsustainable with the number of functions needed to do the simple tasks above.
I have experimented with making the Interface have a template parameter, such as..
// Base Class
template<Variance Variant>
class Interface…
// Specialized
template<>
class Interface<Variance::Interval>…
// Functions to create Interval Instances
//Specialized
template<>
class Interface<Variance::Weighted>…
// Functions to create Weighted Instances
But, I once again run into it becoming unsustainable.
The last thing I am currently looking into is Type Traits, but am unsure if or how that could be implemented to make this simpler.
Without following all of it really in detail, don't you just want e.g.
template<typename T, Variance Type>
auto CreateBaseInstance(T t, int value) {
// Instead of `auto` maybe `std::unique_ptr<BaseType<T, Type>>`
auto OutObj = std::make_unique<FinalType<T, Type>>(t);
if constexpr(Type == Variance::Weighted) {
OutObj->SetWeight(value);
} else if constexpr(Type == Variance::Interval) {
OutObj->SetInterval(value);
}
return OutObj;
}
(I replaced new with std::make_unique, because using raw new like this is generally considered bad practice due to the memory management problems it causes.)
Suppose I have some types
class A {…};
class B {…};
class C {…};
...
And I have some other classes that does various things on objects of these types
class process1
{
public:
void do_stuff(std::vector<A>& …);
};
class process2
{
public:
void do_stuff(std::vector<B>& …);
void do_stuff(std::vector<C>& …);
};
...
These "process" classes share some common interface (do_stuff()), so naturally I want to make an class/template to "regulate" how these classes should be written. I want to have something like
template <class T>
class process_interface
{
public:
virtual void do_stuff(std::vector<T>& …)
{
// Default implementation.
}
// I might also want this.
// virtual void do_other_stuff(std::vector<T>& …) = 0;
};
and let process1 and process2 derive from it. In this way I'm saying that all "process" classes should have a do_stuff(), and that one doesn't necessarily need to write it explicitly because there a default version.
But of course this doesn't work, because process2 has 2 versions of do_stuff(). (Some other "process" classes may have more.) So is there a way to achieve what I want to with this "interface" class/template? I was thinking using a variadic template but I suppose that won't work either.
For now what I have is this:
class process_interface
{
public:
template <class T>
void do_stuff(std::vector<T>& …)
{
// Default implementation.
}
// template <class T>
// void do_other_stuff(std::vector<T>& …)
// {
// throw std::runtime_error("Nope.");
// }
};
But it has problems. For one, do_stuff() cannot be virtual/pure virtual. And if I have other methods that need the same treatment, like the do_other_stuff() there, there's no way to force the subclasses to have a do_other_stuff() for each type that one can do_stuff() on.
Maybe you can make process2 (and all classes with need of more do_stuff() a sort of variadic self inheriting class.
Something as
template <typename...>
struct process2;
template <typename T>
struct process2<T> : public process_interface<T>
{ };
template <typename T0, typename ... Ts>
struct process2<T0, Ts...> : public process_interface<T0>,
public process2<Ts...>
{
using process_interface<T0>::do_stuff;
using process2<Ts...>::do_stuff;
};
The following is a full working example
#include <vector>
class A {};
class B {};
class C {};
class D {};
template <typename T>
struct process_interface
{
virtual void do_stuff (std::vector<T> const &)
{ }
};
struct process1 : public process_interface<A>
{ };
template <typename...>
struct process2;
template <typename T>
struct process2<T> : public process_interface<T>
{ };
template <typename T0, typename ... Ts>
struct process2<T0, Ts...> : public process_interface<T0>,
public process2<Ts...>
{
using process_interface<T0>::do_stuff;
using process2<Ts...>::do_stuff;
};
int main ()
{
process1 p1;
process2<B, C, D> p2;
p1.do_stuff(std::vector<A>{});
p2.do_stuff(std::vector<B>{});
p2.do_stuff(std::vector<C>{});
p2.do_stuff(std::vector<D>{});
}
Starting from C++17, there is no needs of a self-recursive process2: you can use unpacking using and process2 simply become
template <typename ... Ts>
struct process2 : public process_interface<Ts>...
{
using process_interface<Ts>::do_stuff ... ;
};
Use your first version and use multiple inheritance:
class process2 : process_interface<B>, process_interface<C> {
public:
using process_interface<B>::do_stuff;
using process_interface<C>::do_stuff;
};
Note the using declarations bring do_stuff in the base classes to process2 itself, so both can be found by name lookup, then participate in overload resolution.
A Complete Example
This is a great case to illustrate why common functionallity sharing is better handled through composition than inheritance.
Here's a super simple way of getting what you want without any inheritance whatsoever:
class common_interface {
template <class T>
void do_stuff(std::vector<T>& …)
{
//...
}
};
class process_1 {
common_interface common_;
public:
void do_stuff(std::vector<A>& v) {
common_.do_stuff(v);
//...
}
};
class process_2 {
common_interface common_;
public:
void do_stuff(std::vector<B>& v) {
common_.do_stuff(v);
//...
}
void do_stuff(std::vector<C>& v) {
common_.do_stuff(v);
//...
}
};
I'm trying to write a template class that defines its template based on the template implementation of a interface. To clarify my problem, here a example.
template<typename T>
class A{
virtual T getValue() = 0;
}
class B : public A<int>{
//does some things and implements getValue
}
//template definition
//T should become int by passing class B
class C{
A* aPointer;
T previousValue;
}
I've tried template template (not a typing error) syntax, explained really nice in this post. What are some uses of template template parameters in C++?. But because the type of A is determent in the definition of B it doesn't work.
How should i go about and create a template that determines T.
You can't determine the type of T directly from B, but you can from its interface. The best way of handling this would be to add a typedef of T to A.
template<typename T>
class A{
virtual T getValue() = 0;
public:
typedef T ValueType;
}
class B : public A<int>{
//does some things and implements getValue
}
template<class T>
class C {
A<typename T::ValueType>* aPointer;
typename T::ValueType previousValue;
}
Define a named type alias in class interfaces.
The standard library also does this.
template<typename T>
class A{
public:
using value_type = T;
virtual value_type getValue() = 0;
};
class B : public A<int>{
public:
using A<int>::value_type;
//does some things and implements getValue
value_type getValue() override { return 0; }
};
//template definition
//T should become int by passing class B
template<class Derived>
class C{
public:
using value_type = typename Derived::value_type;
A<value_type>* aPointer;
value_type previousValue;
};
int main()
{
C<B> c;
auto x = c.aPointer->getValue();
}
You can use a support function of which you don't even have to give a definition.
It follows a minimal, working example:
#include<type_traits>
#include<utility>
template<typename T>
class A{};
class B : public A<int>{};
template<typename T>
T a_type(const A<T> &);
template<typename T>
class C {
public:
using type = decltype(a_type(std::declval<T>()));
};
int main() {
static_assert(std::is_same<C<B>::type, int>::value, "!");
}
The good part of this approach is that you don't have to modify neither A nor B.
The derived class hides the name of an overload set from the base class if the derived class has the same name defined, but we can always introduce that overload set back with using-declaration:
template <class BASE>
class A : public BASE
{
public:
using BASE::some_method;
void some_method();
}
But what if I introduce all overload sets from variadic base classes?
Would I be able to write something like this?
template <class... BASES>
class A : public BASES...
{
public:
using BASES::some_method...;
void some_method();
}
I've considered using a helper class like:
template <class... BASES>
struct helper;
template <>
struct helper<> {};
template <class OnlyBase>
struct helper<OnlyBase> : OnlyBase
{
using OnlyBase::some_method;
};
template <class Base1, class... OtherBases>
struct helper<Base1, OtherBases> : public Base1, public helper<OtherBases...>
{
using Base1::some_method;
using helper<OtherBases...>::some_method;
};
And it does work. But it requires a lot of typing (of course I can use macro but I try to use c++'s compile-time feature whenever possible), and when I want to introduce more methods, i have to change much in that piece of code.
A perfect answer would be a simple syntax, but if there's none, I will go with the helper class.
Here is a trick how to reduce handwriting:
// U<X,Y> is a binary operation on two classes
template<template<class,class>class U, class... Xs> struct foldr;
template<template<class,class>class U, class X> struct foldr<U,X> : X {};
template<template<class,class>class U, class X, class... Xs> struct foldr<U,X,Xs...> : U<X, foldr<U,Xs...>> {};
// our operation inherits from both classes and declares using the member f of them
template<class X, class Y> struct using_f : X,Y { using X::f; using Y::f; };
struct A { void f(int) {} };
struct B { void f(char) {} };
struct C { void f(long) {} };
struct D : foldr<using_f, A, B, C> {};
int main() {
D d;
d.f(1);
d.f('1');
d.f(1L);
return 0;
}
So we should write foldr once, then write simple ad-hoc operations - using_f, using_g, using_f_g
Maybe there is a way to further simplifying. Let me think a bit...
The derived class hides the name of an overload set from the base class if the derived class has the same name defined, but we can always introduce that overload set back with using-declaration:
template <class BASE>
class A : public BASE
{
public:
using BASE::some_method;
void some_method();
}
But what if I introduce all overload sets from variadic base classes?
Would I be able to write something like this?
template <class... BASES>
class A : public BASES...
{
public:
using BASES::some_method...;
void some_method();
}
I've considered using a helper class like:
template <class... BASES>
struct helper;
template <>
struct helper<> {};
template <class OnlyBase>
struct helper<OnlyBase> : OnlyBase
{
using OnlyBase::some_method;
};
template <class Base1, class... OtherBases>
struct helper<Base1, OtherBases> : public Base1, public helper<OtherBases...>
{
using Base1::some_method;
using helper<OtherBases...>::some_method;
};
And it does work. But it requires a lot of typing (of course I can use macro but I try to use c++'s compile-time feature whenever possible), and when I want to introduce more methods, i have to change much in that piece of code.
A perfect answer would be a simple syntax, but if there's none, I will go with the helper class.
Here is a trick how to reduce handwriting:
// U<X,Y> is a binary operation on two classes
template<template<class,class>class U, class... Xs> struct foldr;
template<template<class,class>class U, class X> struct foldr<U,X> : X {};
template<template<class,class>class U, class X, class... Xs> struct foldr<U,X,Xs...> : U<X, foldr<U,Xs...>> {};
// our operation inherits from both classes and declares using the member f of them
template<class X, class Y> struct using_f : X,Y { using X::f; using Y::f; };
struct A { void f(int) {} };
struct B { void f(char) {} };
struct C { void f(long) {} };
struct D : foldr<using_f, A, B, C> {};
int main() {
D d;
d.f(1);
d.f('1');
d.f(1L);
return 0;
}
So we should write foldr once, then write simple ad-hoc operations - using_f, using_g, using_f_g
Maybe there is a way to further simplifying. Let me think a bit...