使用'this'指针初始化std::array

3

我正在尝试在模板类中初始化一个数组,并将this指针传递给数组中的所有元素。以下是我的类可能的样子:

template<int NUM> class outer_class;

template<int N>
class inner_class {
  private:
   outer_class<N> *cl;
  public:
   inner_class(outer_class<N> *num) {
    cl = num;
   }
   void print_num() {
    cl->print_num();
   }

};

template<int NUM> class outer_class {
 private:
  int number = NUM;

  // --> here I basically want NUM times 'this' <-- 
  std::array<inner_class<NUM>, NUM> cl = { this, this, this, this }; 

 public:

  void print_num() {
    std::cout << number << std::endl;
  }

  void print() {
    cl[NUM - 1].print_num();
  }
};

int main() {
  outer_class<4> t;
  t.print();

  return 0;
}

我该如何将this指针传递给存储在outer_class数组中的所有inner_class元素(在C++11中)?

2个回答

9

首先,你不能在构造函数或任何其他成员函数之外像这样使用this。在这里,你必须在初始化列表中初始化cl

使用委托构造函数std::*_sequence相关内容:

template<int NUM> class outer_class {
    ...

    template <std::size_t... Integers>
    outer_class(std::index_sequence<Integers...>) 
    : cl{(static_cast<void>(Integers), this)...}
    {}

public:
    outer_class(/* whatever */) : outer_class(std::make_index_sequence<NUM>{}) {}
};

注意事项:

  • 你的print成员函数应该被标记为const,因为它们不修改你的成员变量。
  • cl[NUM - 1].print_num(); 你可能想使用std::array::back()

1
如果序列构造函数是私有的,那不是更好吗? - Rakete1111
@O'Neil 谢谢你的回答,简单易懂。 - Mike van Dyke

4
您可以使用一些辅助函数,然后使用这些函数初始化成员,例如:
template <std::size_t I, class T>
T copy(T t) { return t; }

template <class T, std::size_t... Is>
constexpr std::array<T, sizeof...(Is)> copy_n(T const& t, std::index_sequence<Is...>) {
    return {copy<Is>(t)... };
}

template <class T, std::size_t N>
constexpr std::array<T, N> copy_n(T const& t) {
    return copy_n(t, std::make_index_sequence<N>{});
}

然后在你的类中:

std::array<inner_class<NUM>, NUM> cl;

outer_class() : cl(copy_n<inner_class<NUM>, NUM>(this)) { }

注意:

  • [待验证] 在默认成员初始化程序中不能使用this,因此您需要具有自定义构造函数;
  • 您需要明确指定inner_class<NUM>作为copy_n的第一个模板参数,否则T将被推断为outer_class<NUM>*,虽然存在从outer_class<NUM>*inner_class<NUM>的隐式转换,但不存在从std::array<outer_class<NUM*>, NUM>std::array<inner_class<NUM>, NUM>的转换;
  • 如果您正在使用C++11而不是14或者clang,您可能会收到关于copy_nreturn警告,您可以通过添加额外一对括号{}来摆脱它。

@Someprogrammerdude 谢谢,我其实一直在想那个问题,但是自己没有找到相关信息...我会更新答案。 - Holt
1
或许它可以?看起来运行良好 - Some programmer dude
这看起来很不错,但是是否有一个与c++11兼容的std::make_index_sequence版本? - Mike van Dyke
1
@MikevanDyke 不是直接的,你可以在网上找到实现,例如 https://gist.github.com/jappa/62f30b6da5adea60bad3 - Holt
@Holt 非常感谢您的回答和提供的 index_sequence 链接。 - Mike van Dyke
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接