I want to do something similar to the code below, except that I don't want to implement func()
twice because it will be the same implementation. Do you have any proposal how to accomplish this?
template <typename First, typename... Rest>
class Base : public Base<Rest...> {
public:
using Base<Rest...>::func;
void func(First object) {
// implementation
}
};
template <typename First>
class Base<First> {
public:
void func(First object) {
// implementation
}
};
struct X {};
struct Y {};
struct Z {};
class Derived : public Base<X, Y, Z> {};
// ...
Derived d;
d.func(X{});
d.func(Y{});
d.func(Z{});
With multiple inheritance and an additional using
directive:
template <typename First, typename... Rest>
struct Base : Base<First>, Base<Rest...> {
using Base<First>::func;
using Base<Rest...>::func;
};
template <typename First>
struct Base<First> {
void func(First object) {/*...*/}
};
Could be this a solution? (Move definition of func to a common base?)
template <class First>
class Func_impl
{
public:
void func(First obj) {
// implementation
}
}
template <typename First, typename... Rest>
class Base : public Base<Rest...>, Func_impl<First> {
public:
// no need to declare func here
};
template <typename First>
class Base<First> : public Func_impl<First> {
public:
// no need to declare func here
};
I propose to (1) declare Base
as receiving zero or more types
template <typename...>
class Base;
(2) transform the recursive version in a partial specialization that receive one or more types
template <typename First, typename... Rest>
class Base<First, Rest...> : public Base<Rest...> {
public:
using Base<Rest...>::func;
void func(First object) {
// implementation
}
};
(3) delete the only-one-parameter partial specialization and (4) add a ground case zero parameter specialization
template <>
class Base<>
{ public: void func () {} };
Observe the dummy (without implementation) func()
in the ground specialization: it's required (something with the name func
is required) by using Base<Rest...>::func;
.
The following is a full working example.
#include <iostream>
template <typename...>
class Base;
template <typename First, typename... Rest>
class Base<First, Rest...> : public Base<Rest...> {
public:
using Base<Rest...>::func;
void func(First object)
{ std::cout << "func() recursive" << std::endl; }
};
template <>
class Base<>
{ public: void func () {} };
struct X {};
struct Y {};
struct Z {};
class Derived : public Base<X, Y, Z> {};
int main()
{
Derived d;
d.func(X{});
d.func(Y{});
d.func(Z{});
}
In C++17 there is a simple non-recursive solution based on "variadic" multiple inheritance and "variadic using" (pack expansion in using-declaration). Although this is not what you are asking for, I consider it worth an answer. As a bonus, the implementations for each type know their index in the original sequence.
http://coliru.stacked-crooked.com/a/f67d00da68226d5f
#include <iostream>
#include <utility>
template<std::size_t i, class T>
struct IndexedNode {
void func(T) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
template<class Indices, class... Ts>
struct IndexedBase;
template<std::size_t... is, class... Ts>
struct IndexedBase<
std::index_sequence<is...>,
Ts...
>
: IndexedNode<is, Ts>...
{
using IndexedNode<is, Ts>::func...;
};
template<class... Ts>
struct Base
: IndexedBase<std::index_sequence_for<Ts...>, Ts...>
{
using Is = std::index_sequence_for<Ts...>;
using IndexedBase<Is, Ts...>::func;
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.