2017-02-15 22 views
3

У меня есть класс узла шаблона, который принимает целочисленный параметр. У меня также есть древовидный класс, который создает узел и передает его аргумент конструктора в качестве аргумента для шаблона узла.Передача переменной в качестве аргумента шаблона

Tree.cpp

Tree::Tree(int n) { 
    this->n = n; 
    root = new Node<n>(); // compiler error 
} 

main.cpp

Tree *tree = new Tree(2); 

Мой компилятор жалуется, что «п» не является константным выражением. Как успешно передать n в мой класс узлов?

+1

Компилятор собирается должны знать, что 'n' это заранее. Как вы собираетесь ожидать, что он создаст правильный шаблон, если он будет установлен только в отдаленном будущем? «Не постоянное выражение» - это то, что вам нужно отнять. Короткий ответ: вы не можете. Длинный ответ предполагает знание того, что «Node» делает с «n». – tadman

+1

Вы не можете «передать» 'n' вашему классу Node, потому что параметры шаблона не передаются в шаблоны, способ передачи функционального параметра функции. Шаблон и функция - это принципиально разные вещи. C++ просто так не работает. –

+0

шаблоны работают только со значениями, которые известны во время компиляции. 'n' не знает внутри' Tree: Tree' до времени выполнения. Поэтому его нельзя использовать с шаблоном. Вам нужно будет сделать «Tree» сам шаблон и передать 'n' в качестве параметра шаблона. –

ответ

0

Я не думаю, что вы можете так поступить.

n известен во время компиляции, но он не известен как аргумент шаблона. Так как вам нужен n в вашем конструкторе Tree, вы можете создать свой шаблон Tree.

0

Сделайте свой конструктор шаблона один:

struct Base 
{ 

}; 
template <int N> 
struct Node : Base 
{ 

}; 

class Tree 
{ 
public: 

    template <int N> 
    struct size 
    { 
    }; 

    template<int N> Tree(size<N>) { 
     this->n = N; 
     root = new Node<N>(); 
    } 

    int n; 
    Base* root; 
}; 

int main() { 

    Tree t = Tree(Tree::size<2>()); 

    return 0; 
} 
+1

И как бы вы так точно вызвали такой конструктор? 'n' должно быть выводимым. – skypjack

0

, как вы сделали это не может работать, для n должны быть известны во время компиляции.
Вы можете сделать это параметром шаблона конструктора. К сожалению, в этом случае он не может быть явно задан и должен быть выводимым. Это вопрос уродливого синтаксиса, который работает в любом случае.
вытекает минимальный, рабочий пример:

#include<type_traits> 

struct BaseNode {}; 

template<int n> 
struct Node: BaseNode {}; 

struct Tree { 
    template<int n> 
    Tree(std::integral_constant<int, n>) 
     : n{n}, root{new Node<n>()} 
    {} 

    int n; 
    BaseNode *root; 
}; 

int main() { 
    Tree tree{std::integral_constant<int, 2>{}}; 
} 

Обратите внимание, что вы можете легко работать вокруг уродливого синтаксиса с фабричным методом:

struct Tree { 
    template<int n> 
    Tree(std::integral_constant<int, n>) 
     : n{n}, root{new Node<n>()} 
    {} 

    template<int n> 
    static Tree create() { 
     return Tree{std::integral_constant<int, n>{}}; 
    } 

    int n; 
    BaseNode *root; 
}; 

// ... 

Tree tree = Tree::create<2>(); 

Другим возможным решением является создание Node в качестве аргумента и вывести из него n:

struct Tree { 
    template<int n> 
    Tree(Node<n> *node) 
     : n{n}, root{node} 
    {} 

    // ... 
}; 

Или использовать инициализацию два шага и быть ABL е явно передать ваш n в качестве параметра шаблона:

struct Tree { 
    Tree(): n{0}, root{nullptr} {} 

    template<int n> 
    void init() { 
     this->n = n; 
     root = Node<n>; 
    } 

    int n; 
    BaseNode *root; 
}; 

// ... 

Tree tree{}; 
tree.init<2>(); 
Смежные вопросы