C++ - How to introduce overload set from variadic number of bases. - c++

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...

Related

Using declaration on variadic args. How to choose the correct function?

I have a policy based design where I have some function foo() defined in some policies but not others. The base class always inherits from some class called AlwaysBase which has an inferior foo() function.
I want to make it so if a "better" foo() exists (one from a Policy class) that one will always be chosen.
Here is some code:
// logic for determining if a class has a member function (not really related)
template <class> struct sfinae_true: std::true_type{};
template <class T> static auto test_foo(int) -> sfinae_true<decltype(std::declval<T>().foo())>;
template <class> static auto test_foo(long) -> std::false_type;
template <class T> struct has_foo : decltype(test_foo<T>(0)){};
class AlwaysBase{ public: void foo(){ cout << "in AlwaysBase foo()" << endl; } };
class BPolicy{};
class CPolicy{ public: void foo(){ cout << "in Cpolicy foo()" << endl; } };
template<typename T, typename ...Args>
class A: public T, public A<Args...>
{
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};
template<typename T>
class A<T>: public T, public AlwaysBase
{
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};
int main()
{
A<BPolicy> b;
b.foo(); // outputs: In AlwaysBase foo()
A<CPolicy> c;
c.foo(); // outputs: In CPolicy foo()
A<CPolicy, BPolicy> cb;
cb.foo(); // outputs: In CPolicy foo()
A<BPolicy, CPolicy> bc;
bc.foo(); // outputs: In AlwaysBase foo() // I WANT THIS TO OUTPUT!!!!: In CPolicy foo
}
I understand what is happening here, when BPolicy is first, that using statement gets used in the variadic args class first and shadows any preceding using statement that would be found in the terminating base class (namely the CPolicy::foo).
I would like for the order to not matter when specifying policies, and if a Policy has a determinant, that one should always be chosen first over the AlwaysBase::foo.
Use recursion. If empty lists are allowed, this is very easy:
// recursive invariant: As<Ts...>::foo is always the foo from the first capable Ts or from AlwaysBase
template<typename... Ts>
class A : public AlwaysBase { // template<> class A<>
public:
// there are no capable Ts
using AlwaysBase::foo;
};
template<typename T, typename... Ts>
class A<T, Ts...> : public T, public A<Ts...> {
public:
// from the A<Ts...> superclass, not AlwaysBase
// try to use T, fall back to Ts, and only then fall back to AlwaysBase
using std::conditional_t<has_foo<T>::value, T, A<Ts...>>::foo;
};
Constraining to nonempty lists is a bit more annoying:
template<typename T, typename... Ts>
class A : public T, public A<Ts...> {
public:
using std::conditional_t<has_foo<T>::value, T, A<Ts...>>::foo;
};
template<typename T>
class A<T> : public T, public AlwaysBase {
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};
Order still matters, though. If two policies provide foo, the first one wins.

Not fully specified template as template argument in C++

In curiously recurring template pattern I need to change nested type T of TDerivedClass<T> type. Is there a way to specify Base by not fully specified Derived1 class? Something like that: class Derived1 : public Base<T, Derived1<"NOT SPECIFIED TYPE SYNTAX">>, and then fully specify Derived1 but inside Base functions as TDerivedClass<int>. Or is there any other way to change T for this specific part of code?
template<typename T, typename TDerivedClass>
class Base
{
public:
void f()
{
std::vector<T> a;
TDerivedClass b;
TDerivedClass<int> c; // <- want to change T to arbitrary type (to int for example) without changing T
}
};
template<typename T>
class Derived1 : public Base<T, Derived1<T>>
{
};
template<typename T>
class Derived2 : public Base<T, Derived2<T>>
{
};
You probably want template template parameter:
template <typename T, template <typename> class TDerivedClass>
class Base
{
public:
void f()
{
std::vector<T> a;
TDerivedClass<T> b;
TDerivedClass<int> c;
}
};
template<typename T>
class Derived1 : public Base<T, Derived1>
{
};
template<typename T>
class Derived2 : public Base<T, Derived2>
{
};
You can pass the template class specifically:
template<typename T, template<typename> class TDerivedTemplate>
class Base
{
using TDerivedClass = TDerivedTemplate<T>;
public:
void f()
{
std::vector<T> a;
TDerivedClass b;
TDerivedTemplate<int> c;
}
};
template<typename T>
class Derived1 : public Base<T, Derived1> // Pass the template (Derived1) to instantiate new classes from
{
};
// Since you're changing the pattern anyways, you might as well
// have it detect the template from the type
template<typename TDerivedClass>
class Base;
template<template<typename> class TDerivedTemplate, typename T>
class Base<TDerivedTemplate<T>> {
using TDerivedClass = TDerivedTemplate<T>;
public:
void f() { /* Same as above */ }
}
template<typename T>
class Derived1 : public Base<Derived1<T>>
// Automatically gets the template. Also means it's harder to use Base<> wrong.
{
};
Or you can use a rebind type trait:
template<typename ToRebind, typename... NewTypes>
struct rebind;
template<template<typename...> class Template, typename... CurrentTypes, typename... NewTypes>
struct rebind<Template<CurrentTypes...>, NewTypes...> {
using type = Template<NewTypes...>;
}
// Used like
TDerivedClass b;
typename rebind<TDerivedClass, int>::type c;

Is there a work-around for parameter pack expansion in using declarations [duplicate]

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...

What would a CRTP-based solution to this look like?

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?

Interface class for classes with templated function

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