2016-04-25 5 views
5

Я хочу инициализировать размерный массив шаблонов объектов с конструкторами не по умолчанию, как показано в следующем коде:Как инициализировать массив размера шаблона?

#include <array> 

template<std::size_t N> 
class Foo 
{ 
    public: 
     class Bar 
     { 
       Foo<N> & _super; 

      public: 
       Bar(Foo<N> *super) : 
        _super(*super) 
       { 
       } 
     }; 

     std::array<Bar, N> _array; 

     Foo(void) : 
      _array{{}} // We need {this, ...} N times 
     { 
     } 
}; 


int main(void) 
{ 
    Foo<3> foo; 
    (void)foo; 
    return 0; 
} 

ли способ сказать: «Я хочу, чтобы массив N объектов, инициализированы с этим такой же параметр "? Я думаю, что есть способ мета-программирования шаблонов, но я не могу понять, как это сделать.

+0

Не должен быть конструктором 'Bar'' Bar (Foo & super): _super (super) '? Или член 'Foo & _super' должен быть' Foo * _super'? – wally

+0

@flatmouse ничего не меняет, нет? Я мог бы написать его и построить Bar, как следует «Bar (* this)»; но это не помогает решить вопрос. – Boiethios

+0

Ах, ну, вы берете указатель, который затем откладывается для инициализации ссылочного элемента. Я пытался понять. Я получаю это сейчас. – wally

ответ

2

Вы можете просто продолжать добавлять один this в то время, пока вы не N из них, в какой момент вы просто инициализировать _array:

Foo() 
    : Foo(this) 
    { } 

private: 
    template <class... T, std::enable_if_t<(sizeof...(T) < N), void*> = nullptr> 
    Foo(T... args) 
    : Foo(args..., this) 
    { } 

    template <class... T, std::enable_if_t<(sizeof...(T) == N), void*> = nullptr> 
    Foo(T... args) 
    : _array{{args...}} 
    { } 
+0

@Boiethios Оптимальный подход 'index_sequence'. – Barry

+0

Можно ли написать этот код в C++ 11 ('enable_if_t' is C++ 14)? Например, с параметром шаблона 'size_t I', который будет уменьшаться, и специализированной версией' <0> '? Я пытаюсь это сделать, но у меня проблемы с написанием шаблонов. – Boiethios

+0

@Boiethios 'enable_if_t' - это просто шаблон псевдонима, вы можете просто скопировать определение в C++ 11. – Barry

9

Все возможно с небольшой помощью make_index_sequence:

Foo() : Foo(std::make_index_sequence<N>()) {} 
    template <size_t... I> Foo(std::index_sequence<I...>) : _array{((void)I, this)...} {} 

Обратите внимание на оператор запятой (,) в конструкторе _array - любезно предоставлен @Quentin (в отличие от вызова функции).

+4

Вы можете заменить вызов функции оператором запятой: '_array {(I, this) ...}' :) – Quentin

+0

@Quentin, хорошо поймать! Будет включать, если вы не возражаете. – SergeyA

+0

Конечно! Я не хотел публиковать ответ, который бы был идентичен вашему, за исключением этой настройки. – Quentin

Смежные вопросы