简体   繁体   English

初始化嵌套的模板类

[英]Initialize nested template classes

I have many template classes, which work in a arbitrary order together (share the same concept). 我有许多模板类,它们以任意顺序一起工作(共享相同的概念)。

Supposing that I have: 假设我有:

template<typename T>
class A {
  T t_;
public:
  void call() {
    // Do something.
    t_.call();
  }
};

template<typename T, typename U>
class B {
  T t_;
  U u_;
public:
  void call() {
    // Do something.
    t_.call();
    // Do something.
    u_.call();
  }
};

class C {
public:
  void call() {
    // Do something.
  }
};

And I have the following instantiated class: 我有以下实例化的类:

using Foo = A<B<A<C>,C>>;

Lets assume, C need a special constructor (or initializer function) to work probably. 让我们假设,C可能需要一个特殊的构造函数(或初始化函数)。 Something I do only know at runtime. 我只在运行时才知道的东西。

struct C {
  void init(int);
  void call();
};

How can I initialize Foo probably? 我如何初始化Foo? Or any other nested class combination? 还是任何其他嵌套类组合?

My current workaround is to define C as: 我当前的解决方法是将C定义为:

template<typename I>
struct C {
  C() : var_(I::get())
  void call();
};

And create Foo inside a function: 并在函数内部创建Foo:

int main()
{
  int i = 0;

  struct HelperC1 {
    static int get(bool set = false, int value = 0) {
      static int value_ = value;
      if (set) value_ = value;
      return value_;
    }
  } helperC1;

  struct HelperC2 {
    static int get(bool set = false, int value = 0) {
      static int value_ = value;
      if (set) value_ = value;
      return value_;
    }
  } helperC2;

  helperC1.get(true, i);
  helperC2.get(true, i+1);

  A<B<A<C<HelperC1>>,C<HelperC2>>> foo;   
  foo.call();

  return 0;
}

Live example. 现场示例。

You see, this workaround is not very handy. 您会发现,此解决方法不是很方便。 Another approach would be to call the first constructor of Foo with the arguments and redirect them to C but this is very bad for different class combinations like: 另一种方法是使用参数调用Foo的第一个构造函数,并将它们重定向到C,但这对于不同的类组合(例如:

using Bar = A<B<A<C>,<B<B<A,C>,C>>>;

Question: How to initialize nested (template) classes with a runtime arguments (better/in a nicer, cleaner way)? 问题:如何使用运行时参数(更好/更简洁的方式)初始化嵌套(模板)类?

You could use pointers and build foo with already constructed and initialized objects. 您可以使用指针,并使用已构造和初始化的对象来构造foo ie: 即:

UNTESTED CODE 未测试的代码

template<typename T>
 class A {
  T* t_;

public:
  A(T* valptr) : t_(valptr){}
  ~A(){ delete t_ ; }

  void call() {
    // Do something.
    t_.call();
  }
};

template<typename T, typename U>
class B {
  T* t_;
  U* u_;

public:
  B(T* val1ptr, U* val2ptr):t_(val1ptr), u_(val2ptr){}
  ~B(){delete val1ptr; delete val2ptr;}

  void call() {
    // Do something.
    t_->call();
    // Do something.
    u_->call();
  }
};

class C {
  private:
    int x_;
  public:
  C(int x):x_(x){}
  void call() {
    // Do something.
  }
};

Usage: 用法:

A<B<A<C>,C>> foo( new B<A<C>,C>(new A<C>(new C(3) ), new C(3) ) );

This example builds values for branching template types with move construction and forwarding helper functions. 本示例使用移动构造和转发帮助器功能为分支模板类型构建值。

The forwarding helpers wrap constructors, using type inference to avoid the need to specify each constructor with its complicated parameters. 转发助手使用类型推断来包装构造函数,以避免需要为每个构造函数指定复杂的参数。

In this example, the call() function dumps the parameter structure and values of an object's children. 在此示例中,call()函数转储对象的子代的参数结构和值。

#include <iostream>
#include <utility>

template<typename T>
class A {
    T t;
public:
    A(T&& t) : t{std::move(t)} {}
    void call() {
        std::cout << "A<";
        t.call();
        std::cout << ">";
    }
};
template <typename T>
inline A<T> mkA(T&& t) { return A<T>{std::forward<T>(t)}; }

template<typename T, typename U>
class B {
    T t;
    U u;
public:
    B(T&& t, U&& u) : t{std::move(t)}, u{std::move(u)} {}

    void call() {
        std::cout << "B<";
        t.call();
        std::cout << ",";
        u.call();
        std::cout << ">";
    }
};
template <typename T, typename U>
inline B<T,U> mkB(T&& t, U&& u) { 
    return B<T,U>{std::forward<T>(t), std::forward<U>(u)};
}

class C {
    int c;
public:
    C(int c) : c{c} {}
    void call() {
        std::cout << "C(" << c << ")";
    }
};

int main() {
    auto bar = mkA(mkB(mkA(C{1}), mkB(mkB(mkA(C{2}),C{3}), C{4})));
    bar.call();
    std::cout << '\n';
}

This outputs: 输出:

A<B<A<C(1)>,B<B<A<C(2)>,C(3)>,C(4)>>>

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

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