I have a template node class that takes an integer parameter. I also have a tree class that creates a node and passes its constructor argument as the argument for the node template.
Tree.cpp
Tree::Tree(int n) {
this->n = n;
root = new Node<n>(); // compiler error
}
main.cpp
Tree *tree = new Tree(2);
My compiler complains that 'n' is not a constant expression . How do I successfully pass n
to my node class?
I don't think you can do like that.
n
is known at compile time, but it is not known as a template argument. Since you need n
in your Tree
constructor, you could make your Tree
class a template too.
Make your constructor a template one:
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;
}
The way you did it cannot work, for n
must be known at compile-time.
You can make it a constructor template parameter. Unfortunately, in this case, it cannot be explicitly given and must be deducible. It's a matter of an ugly syntax that works anyway.
It follows a minimal, working example:
#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>{}};
}
Note that you can easily work around the ugly syntax with a factory method:
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>();
Another possible solution is to provide a Node
as an argument and deduce n
from it:
struct Tree {
template<int n>
Tree(Node<n> *node)
: n{n}, root{node}
{}
// ...
};
Or use a two steps initialization and be able to explicitly pass your n
as a template parameter:
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>();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.