I'm trying to write an implementation of a 2-3-4 tree in c++. I'm it's been a while since I've used templates, and I'm getting some errors. Here's my extremely basic code framework:
node.h:
#ifndef TTFNODE_H
#define TTFNODE_H
template <class T>
class TreeNode
{
private:
TreeNode();
TreeNode(T item);
T data[3];
TreeNode<T>* child[4];
friend class TwoThreeFourTree<T>;
int nodeType;
};
#endif
node.cpp:
#include "node.h"
using namespace std;
template <class T>
//default constructor
TreeNode<T>::TreeNode(){
}
template <class T>
//paramerter receving constructor
TreeNode<T>::TreeNode(T item){
data[0] = item;
nodeType = 2;
}
TwoThreeFourTree.h
#include "node.h"
#ifndef TWO_H
#define TWO_H
enum result {same, leaf,lchild,lmchild,rmchild, rchild};
template <class T> class TwoThreeFourTree
{
public:
TwoThreeFourTree();
private:
TreeNode<T> * root;
};
#endif
TwoThreeFourTree.cpp:
#include "TwoThreeFourTree.h"
#include <iostream>
#include <string>
using namespace std;
template <class T>
TwoThreeFourTree<T>::TwoThreeFourTree(){
root = NULL;
}
And main.cpp:
#include "TwoThreeFourTree.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream inFile;
string filename = "numbers.txt";
inFile.open (filename.c_str());
int curInt = 0;
TwoThreeFourTree <TreeNode> Tree;
while(!inFile.eof()){
inFile >> curInt;
cout << curInt << " " << endl;
}
inFile.close();
}
And when I try to compile from the command line with:
g++ main.cpp node.cpp TwoThreeFourTree.cpp
I get the following errors:
In file included from TwoThreeFourTree.h:1,
from main.cpp:1:
node.h:12: error: ‘TwoThreeFourTree’ is not a template
main.cpp: In function ‘int main()’:
main.cpp:13: error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> class TwoThreeFourTree’
main.cpp:13: error: expected a type, got ‘TreeNode’
main.cpp:13: error: invalid type in declaration before ‘;’ token
In file included from node.cpp:1:
node.h:12: error: ‘TwoThreeFourTree’ is not a template
In file included from TwoThreeFourTree.h:1,
from TwoThreeFourTree.cpp:1:
node.h:12: error: ‘TwoThreeFourTree’ is not a template
My main question is why it's saying "error: ‘TwoThreeFourTree’ is not a template". Does anyone have any ideas? Thanks for all advice/help in advance...
Dan
The solution that has been accepted has the slight problem of opening your class to any instantiation of the TwoThreeFourTree template, not only those that share the same instantiation type.
If you only want to open the class to instantiations of the same type you can use the following syntax:
template <typename T> class TwoThreeFourTree; // forward declare the other template
template <typename T>
class TreeNode {
friend class TwoThreeFourTree<T>;
// ...
};
template <typename T>
class TwoThreeFourTree {
// ...
};
You just need to declare it as a template when you use the friend keyword. You're using incorrect syntax for a friend declaration in your code. What you want to write is:
template <class U> friend class TwoThreeFourTree;
Related
say i have a class A which is templatized in some namespace NameSpaceA.
i wish to use the forward declaration in some other header file . I am able to achieve this using the following syntax
File 1.h
namespace NameSpaceA
{
template <typename T>
class A
{
public:
void foo();
}
}
code that works for me
File 2.h
//forward declaration
namespace NameSpaceA
{
template <typename T>
class A;
}
class B
{
private:
vector<NameSpaceA::A<specialization>* > mABC;
}
but i want to code it with the using keyword.
I tried the following syntax
(code that fails)
File 2.h
//forward declaration
namespace NameSpaceA
{
template <typename T>
class A;
}
using A = typename NameSpaceA::A<specialization>;
class B
{
private:
vector<A>* > mABC;
}
but vector declaration errors out with the message template argument 1 is invalid. Can someone please help me write this elegant way.
I am trying to set variable name of template class A by it's definition.
I was inspired by this answer.
My current files looks like this:
Header file
namespace N {
// Definition of class A
template <class T> class A {
public:
A();
static const char* name;
}
/*1*/ #define REGISTER_TYPE(T) template <> class N::A<T>::name = #T;
}
Source file
namespace N {
template<class T>
A<T>::A()
{
//empty constructor
}
}
REGISTER_TYPE(N::MyOtherClass);
But somehow, error messages 'name' in 'class N::A<N::MyOtherClass>' does not name a type and expected unqualified-id before '=' token (line with /*1*/) pops up, but variable with this name exists.
I am using C++17. I have already tried to
Where am I doing mistake?
Thanks for your help!
//EDIT:
Solved in comments. Result is:
#define REGISTER_TYPE(T) template <> const char * N::A<T>::name = #T;
I'm trying to implement a Template while separating the Header and Implementation file.
I'm getting this error when building the project:
error C2955: 'Series': use of class template requires template
argument list
Header.h
#ifndef SERIES_H
#define SERIES
template <class T>
class Series {
private:
T var;
public:
Series(T v);
};
#endif
Implementation.cpp
#include <iostream>
#include "Header.h"
template <class T>
Series::Series(T v) {
var = v;
std::cout << var;
}
Main.cpp
#include <iostream>
#include "Header.h"
int main() {
Series<int> w(10);
}
The project builds successfully when everything is in one file
What do I need to do to make this work?
I am realizing a templated Stack structure on the base of vector in C++. I am not sure what is wrong with my code.
Stack.h
#ifndef STACK_H_
#define STACK_H_
#include <vector>
using namespace std;
template <class T>
class Stack {
public:
Stack();
virtual ~Stack();
bool empty();
int size();
void push(T pushvar);
T pop();
private:
std::vector<T> container;
};
#endif /* STACK_H_ */
Stack.cpp
#include "Stack.h"
#include <vector>
//template <class T>
Stack::Stack()
:container(0)
{
}
Stack::~Stack() {
// TODO Auto-generated destructor stub
}
bool Stack::empty(){
return (container.empty());
}
Even before calling anything from the main, Eclipse gives me several errors. But I will give an exemplary main:
#include <iostream>
#include "Stack.cpp"
using namespace std;
int main() {
Stack<int> s;
cout << s.empty();
return (0);
}
The compiler returns the following errors:
Description Resource Path Location Type
'container' was not declared in this scope Stack.cpp /PracticeCpp/src line 23 C/C++ Problem
'template<class T> class Stack' used without template parameters Stack.cpp /PracticeCpp/src line 22 C/C++ Problem
invalid use of template-name 'Stack' without an argument list Stack.cpp /PracticeCpp/src line 12 C/C++ Problem
invalid use of template-name 'Stack' without an argument list Stack.cpp /PracticeCpp/src line 18 C/C++ Problem
Member declaration not found Stack.cpp /PracticeCpp/src line 12 Semantic Error
Member declaration not found Stack.cpp /PracticeCpp/src line 18 Semantic Error
Member declaration not found Stack.cpp /PracticeCpp/src line 22 Semantic Error
Method 'empty' could not be resolved Stack.cpp /PracticeCpp/src line 23 Semantic Error
Symbol 'container' could not be resolved Stack.cpp /PracticeCpp/src line 13 Semantic Error
I know that I haven't realized all the methods declared in the header file, but this is not my problem. Before I continue realizing them I want to understand where am I wrong?
Correction after the answers:
I followed the suggestions in the answers but still I don't get what continues to be wrong. I moved the template realizations to the header. I deleted the other unrealized methods to avoid confusion. Now my .cpp file is empty.
My new header file:
#ifndef STACK_H_
#define STACK_H_
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
template <typename T>
Stack<T>::Stack() : container(0)
{
}
template <class T>
bool Stack::empty() {
return container.empty();
}
};
#endif /* STACK_H_ */
definition should be
template <typename T>
Stack<T>::Stack() : container(0)
{
}
And not in .cpp
The method Stack::empty() was never declared, you declared Stack<T>::empty(). The same is true for each other constructor, operator and method. Add a template declaration to each implementation to fix this error. Notice that the error message hints at the mistake by saying "invalid use of template-name 'Stack' without an argument list".
Example :
template<class T> bool Stack<T>::empty() {
return container.empty();
}
Implementations for template methods should be included in header files. See this question.
Edit :
Regarding your newest example, you've mixed up two solutions. Try either :
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
Stack() : container(0)
{
}
bool empty() {
return container.empty();
}
};
OR
#include <vector>
template <class T>
class Stack {
private:
std::vector<T> container;
public:
Stack();
bool empty();
};
template<class T>
Stack<T>::Stack() : container(0)
{
}
template<class T>
bool Stack<T>::empty()
{
return container.empty();
}
In the first solution, you are defining your functions within the definition of your class. The compiler knows that you are working on class Stack<T>, you mustn't remind it. In the second solution, the functions are defined outside the class. Here, you must specify which class' empty method and constructor you are defining.
In one of my projects I have a tree data structure, that might contain values of a generic type T.
In order to reduce compilation times and dependencies I tried to move implementation details from the tree node class Node to class NodeImpl. The internals of Node are private and should be only accessed at defined entry points, for example by the getName function.
Only people that are interested in using getName should include NodeImpl in their source files. This is how I think to reduce my compilation times and dependencies.
But for some reason the following three toys classes will not compile. It says no access to private members. What I'm doing wrong?
File main.cpp:
#include <iostream>
#include "Node.h"
#include "NodeImpl.h"
int main(int argc, char** args) {
Node<int> n("Test", 2);
std::cout << getName(n) << std::endl;
}
File Node.h:
#pragma once
#include <string>
template<typename T>
class NodeImpl;
template<typename T>
class Node {
public:
typedef T value_type;
Node(const std::string& name, const T& value) : name(name), value(value) {}
private:
std::string name;
T value;
friend class NodeImpl<T>;
};
File NodeImpl.h:
#pragma once
#include "Node.h"
template<typename T>
std::string getName(Node<T>& n);
template<typename T>
class NodeImpl {
NodeImpl(Node<T>& node) : mNode(node) {
}
Node<T>& mNode;
std::string name() {
return mNode.name;
}
friend std::string getName(Node<T>& n);
};
template<typename T>
std::string getName(Node<T>& n) {
auto x = NodeImpl<T>(n);
return x.name();
}
The warning produced by GCC gives insight:
warning: friend declaration 'std::__cxx11::string getName(Node<T>&)' declares a non-template function [-Wnon-template-friend]
friend std::string getName(Node<T>& n);
^
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
In other words, your class NodeImpl<int> was befriending a global function std::string getName(Node<int> &), which is unrelated to the function std::string getName<int>(Node<int> &) instantiated from the function template template <class T> std::string getName(Node<T> &) for T = int.
So the correct solution is this:
template<typename T>
class NodeImpl {
// ... as before ...
friend std::string getName<T>(Node<T>& n);
};
This [live example] shows that this solution indeed works.