简体   繁体   English

具有递归继承和使用声明的可变参数模板

[英]variadic template with recursive inheritance and using declaration

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. 我想做类似下面的代码,除了我不想实现func()两次,因为它将是相同的实现。 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: 使用多重继承和附加的using指令:

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) {/*...*/}
};

Live Demo (C++11) 现场演示(C ++ 11)

Could be this a solution? 这可能是一个解决方案吗? (Move definition of func to a common base?) (将func的定义移到公共基础?)

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 我建议(1)将Base声明为接收零个或多个类型

template <typename...>
class Base;

(2) transform the recursive version in a partial specialization that receive one or more types (2)在接收一种或多种类型的部分特化中转换递归版本

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 (3)删除只有一个参数的部分特化和(4)添加一个接地情况零参数特化

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; 观察地面专业化中的虚拟(没有实现) func()using Base<Rest...>::func;它是必需的(需要名称为func东西) 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). 在C ++ 17中,有一个基于“可变参数”多重继承和“可变参数使用”的简单非递归解决方案(使用声明中的包扩展)。 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 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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM