Template program sum of linked list values - templates

I have the below code which i am planning to use it for sum or node values of a list.
#include <iostream>
#include <string>
using namespace std;
template <typename T, typename U, T node>
struct Sum {
static const U sum = Sum<T,U,node->next>::sum + node->value;
};
template <typename T,typename U, NULL>
struct Sum {
static const U sum = {};
};
template <typename T>
struct Node {
T value;
Node* next;
Node() {
value = {};
next = NULL;
}
};
int main()
{
Node<string>* n1;
n1->value = "Hello";
Node<string>* n2;
n2->value = "World!";
n1->next = n2;
const Node<string>* const nx=static_cast<const Node<string>* const>(n1);
const string str=Sum<Node<string>*, string, nx>::sum;
return 0;
}
I get the below errors.
1>templatemetaprogramming.cpp(15):
error C2059: syntax error: 'constant'
1>templatemetaprogramming.cpp(18):
error C2976: 'Sum': too few template arguments 1>
1>templatemetaprogramming.cpp(16):
note: see declaration of 'Sum'
First one i think is because i cannot use NULL as constant to Node*
second one seems to be the same, i did cast to a constant the Node pointer. Can anyone help to fix it? Thank you

You try to compute something at compile time which is only available at runtime. In fact this is the whole point of a linked list (it is a dynamic data structure which is unknown before running the program). So the computation of it's sum definetly has to happen at compile time.
Templates are evaluated at compile time. Therefore you can only pass constant expressions to a template but no expressions that will only be known at runtime.
I am quite sure you added all the const and static_cast keywords in the following piece of code, because the compiler complained about being unable to use non-const expressions in that context or something similar:
const Node<string>* const nx=static_cast<const Node<string>* const>(n1);
const string str=Sum<Node<string>*, string, nx>::sum;
If you look at it, semantically this just doesn't make any sense. Let's say you wrote this originally (just to remove some complexity):
Node<string>* nx = new Node<string>(n1);
string str = Sum<Node<string>*, string, nx>::sum;
What will this evaluate to? Let's play preprocessor for a while (Sure a compiler is much smarter, but I am not):
The first expression will instantiate an object of the following type
struct Node {
string* value;
Node* next;
Node() {
value = {};
next = NULL;
}
};
The second line something like:
struct Sum {
static const string sum = Sum<Node<string>*, string, nx->next>::sum + nx->value;
};
What is nx in that context? This doesn't make sense, right? Again, this is not what the compiler does, but you hopefully get the idea.
I edited your code to do what you (probably) want. (Working example here)
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct Node {
T value;
Node* next;
Node() {
value = T();
next = NULL;
}
static T sum(Node<T> *node) {
T s;
Node<T> *next = node;
while(next != NULL) {
s = s + next->value;
next = next->next;
}
return s;
}
};
int main()
{
Node<string> n1 = Node<string>();
n1.value = string("Hello");
Node<string> n2 = Node<string>();
n2.value = string("World!");
n1.next = &n2;
string str = Node<string>::sum(&n1);
cout << str << endl;
return 0;
}
Note:
Besides from the things I mentioned above your code has many other issues. This for example
Node<string>* n1;
n1->value = "Hello";
will lead to undefined behavior and most likely to a segmentation fault as the content of n1 is not defined. I don't know your c++ knowledge but I think you should learn about pointers, stack, heap and so on before learining anything about templates.

What you want to achieve is impossible, you can not mix compilation time computation and runtime execution: in your case, linked list is created at runtime. But your template instantiation is done at compilation time: compiler is not able to predict how many template it has to create to run through complete list.
What you want to do has to be done with standard function, not with template. You only can use template for static data, like type, but definitively not for runtime variable. Runtime variable should be pass as a function parameter. So, you can have a function like this:
template <typename T, typename U>
U Sum(T *node)
{
// run through complete list by iteration or recursion to do sum
}
You can achieve what you want by a lot of different possible designs. Just take care that runtime data is passed as function parameter.
If you want to iterate over static data, you can use variadic template.
And in C++11 std::string is always a runtime data, it can not be used as a constant expression

Related

using a template with a struct incomplete type error

#include <iostream>
#include <string>
#include <map>
using namespace std;
template<typename T>
struct Node
{
map<string, T> data;
struct Node* left, * right, * bottom;
Node(map<string, T> data)
{
this->data = data;
left = right = bottom = NULL;
}
};
int main()
{
cout << endl;
map <string, string> test;
test["walid"] = "walid";
struct Node* root = new Node(test); #error here
cout << root->data["walid"];
cout << endl;
return 0;
}
can someone please tell me why I'm getting incomplete type error? I'm trying to get the node to be created with different map value type depending on the data.
can someone please tell me why I'm getting incomplete type error?
Because you're attempting to create a pointer to a type that you haven't defined / attempting to create a dynamic object of type that you haven't defined.
You haven't defined a type called Node. You've defined a class template called Node. You cannot have a Node* for the same reason that you cannot have a std::vector*. This compiler error explains what is going on:
error: template argument required for 'struct Node'
You can instantiate the template to get a class, which is a type. The angle bracket syntax is used to instantiate templates, and to pass the template arguments. Example:
Node<std::string>* root = ...
Note that if you let the compiler to deduce the type of the pointer from the initialiser, then the compiler can implicitly deduce the class template arguments (this language feature was introduced in C++17):
auto* root = new Node(test);
P.S. Your example would leak memory if it compiled. Avoid bare owning pointers. Prefer RAII containers and smart pointers instead. Also avoid dynamic allocation when you don't need it.
Node is not a type, it's a template. Node<string> is the type you are after.
Also, struct in a variable declaration is redundant in C++, so change that line to:
Node<string>* root = new Node<string>(test);
Don't forget to delete root; later -- or you could just make root a value:
Node<string> root{test};
Finally, you can optimize several things here with std::move, such as:
Node(map<string, T> data)
{
this->data = data;
left = right = bottom = NULL;
}
Using initializer lists and std::move you can save a possibly-expensive copy of data:
Node(map<string, T> d) :
data{std::move(d)},
left{nullptr}, right{nullptr}, bottom{nullptr} {}
Likewise, since you never use test again, you could move that into the constructor argument:
Node<string> root{std::move(test)};

Opaque pointer to struct with template members

Suppose I'm building a linked list (the real data structure is completely different, but a linked list suffices for the question) whose nodes look like
template <typename T>
struct node
{
struct node<T> *next;
T data;
};
For my data structure, I have a lot of functions with return type struct node *, and I want the user to treat this type as opaque. In the linked list example, such a function could be for example get_next(struct node<T> *n) or insert_after(struct node<T> *x, struct node<T> *y). Only very few functions, namely those that allocate nodes or get/set their data field, need to know anything about T.
Is there a nicer way to "ignore T" and let the user interact only with something like a typedef struct node * opaque_handle for those functions that don't ever have to care about T? My gut reaction, coming from C, is just to cast to and from void*, but that doesn't sound very elegant.
Edit: CygnusX1's comment has convinced me that I'm asking for too many guarantees from the type system at the same time that I'm trying to circumvent too many of those guarantees. I will fall back to letting T be void * at the cost of casting and indirection.
While you don't care about what T is, you most like want to differenciate it from a different type - say U, don't you?
You probably want the following to raise an error:
node<T>* elem1 = ...
node<U>* elem2 = ...
elem1 = elem2
There are a few ways to make your code simpler without sacrificing the type checking or run-time perforamce:
If you use C++11, consider using auto instead of explicitly naming the type when using your functions
If node<T> is very common in your code, you can set a global-scope typedef
Also note, that in the context of node<T> definition, using a plain node (without template arguments) is allowed.
If you really want to hide the contents of the node, consider implementing the pimpl pattern as suggested by mvidelgauz.
If you can use boost, then boost::any or boost::variant may be able to help implement heterogeneous containers.
Is something like this what you're after?:
#include <iostream>
#include <boost/any.hpp>
#include <list>
using Collection = std::list<boost::any>;
using Node = Collection::iterator;
static Collection anys;
template<typename T>
Node insert_after(T const& obj, Node start_pos = anys.end())
{
return anys.insert(start_pos, boost::any(obj));
}
void print_type(boost::any const& a)
{
if (a.type() == typeid(int)) { std::cout << "int" << std::endl; }
else if (a.type() == typeid(float)) { std::cout << "float" << std::endl; }
}
int main()
{
const auto node1 = insert_after(int(1));
const auto node2 = insert_after(float(2.57));
const auto node3 = insert_after(int(3));
std::cout << boost::any_cast<int>(*node1) << std::endl;
std::cout << boost::any_cast<float>(*node2) << std::endl;
std::cout << boost::any_cast<int>(*node3) << std::endl;
print_type(*node1);
print_type(*node2);
print_type(*node3);
return 0;
}
Outputs:
1
2.57
3
int
float
int

No Match for 'operator' error in C++

#include <iostream>
#include <string>
#include <cstdlib>
#include <cassert>
#include <ctime>
#include <map>
using namespace std;
struct SBLnode {
string name;
SBLnode *next;
SBLnode * left, * right;
};
struct Queue {
SBLnode * first, * last;
};
typedef SBLnode* BST;
struct SBL {
Queue q;
BST root;
};
void SBL_init (SBL& sbl) {
sbl = NULL;
}
I keep getting the following error in GCC when compiling...
error: no match for ‘operator=’ (operand types are ‘SBL’ and ‘long int’)
sbl = NULL;
^
This error basically is for the line sbl = NULL and it would be great if someone could explain to me exactly what that error actually means.
It can't find the operator= for SBL &SBL::operator=(const long int &rhs). There is a better practice. One option is to use a pointer and set it to NULL. NULL evaluates to 0. There is no operator which assigns an int intriniscally to your SBL struct object.
Or define a const static instance of the struct with the initial values and then simply assign this value to your variable whenever you want to reset it.
For example:
static const struct SBL EmptyStruct;
This uses static initialization to set the initial values.
Then, in init you can write:
sbl = EmptyStruct;
Note: Have to compile with -fpermissive in gcc or set EmptyStruct = { }. The reason why you have to set -fpermissive is listed here for GCC 4.6. GCC 4.4 needs EmptyStruct = { }.
Here is your program running. Initially it prints "initial" twice and on the third time, it prints empty string. Meaning, it was set to nothing by the assignment in the init function.
int main()
{
struct SBLnode initial;
initial.name = "initial";
struct Queue q;
q.first = &initial;
cout << q.first->name << endl;
struct SBL testInit;
testInit.q = q;
SBL_init(testInit);
cout << testInit.q.first->name << endl;
return 0;
}
http://ideone.com/Ecm6I9
void SBL_init (SBL& sbl) {
sbl = NULL;
}
Others have already pointed out why that line doesn't compile. Perhaps I can suggest an alternative solution. Instead of providing an init function, why not give all of your structures constructors like so? Is there some reason that you can't provide those? The operator= and copy constructor don't need to be defined if shallow copying of pointers is what you want. Since nodes typically need to be moved around I'm guessing that a shallow copy is fine. You can certainly use the nullptr if using c++ 11 rather than 0. I'm not a big fan of the NULL macro and opinions often vary with regards to NULL.
struct SBL {
SBL() : root(0) {}
Queue q;
BST root;
};
struct Queue {
Queue() : first(0), last(0) {}
SBLnode * first, * last;
};
NULL is a macro which expands to the integer literal 0. There is no intrinsic or user-defined operator which can assign an integer to an object of type SBL.
It looks like you are treating sbl as a pointer; but it is not a pointer, it is a reference.
You probably wanted to write this instead:
void SBL_init (SBL& sbl) {
sbl.root = NULL;
}
This initializes sbl by nulling out its member pointers.
As others have commented, nullptr is preferred in C++11:
void SBL_init (SBL& sbl) {
sbl.root = nullptr;
}
This error means that operator= , which is a function, is not defined in struct SBL. It is required when you write
sbl = NULL;
Solution:
provide SBL& operator=( const long int& i); in struct SBL.
In fact I think that you would like something alike SBL& operator=( BST b):
struct SBL {
Queue q;
BST root;
SBL& operator=( BST b) {
root = b;
return *this;
}
};
It is trying to find an assignment operator that has the form
SBL &SBL::operator=(const long int &rhs):#
and cannot find one.
I guess you were thinking about the pointers.

use operators in templates in c++

I am trying to implement a List class using pointers and am trying to implement a function LOCATE(T x) where T is for the template and returns the first position of the element x if found, else returns last position + 1.
My functions code is
template<class T>
int List<T>::locate(T n) const
{
int size = end();
Node<T> * p = head_;
for (int i = 0; i < size; i++)
{
if (p->data() == n) // fails on this line
return i;
p = p->link();
}
return size; // if no match found
}
I initialise my list with T as string as
List<string> myList;
but I get an error message
'bool std::operator ==(const std::istreambuf_iterator<_Elem,_Traits> &,const std::istreambuf_iterator<_Elem,_Traits> &)' : could not deduce template argument for 'const std::istreambuf_iterator<_Elem,_Traits> &' from 'std::string
Why is the error coming up even though the '==' operator is defined for the string class?
'
The code for Node is
template<typename T>
class Node
{
public:
// Constructors
Node();
Node(T d, Node<T> * l = NULL);
//Inspectors
T data() const;
Node<T> * link() const;
// Mutators
void data(T d); // assigns new value to Node
void link(Node<T> * l); // points this Node to a different one
// Destructor
~Node();
private:
Node<T> * link_;
T data_;
};
template<typename T>
T Node<T>::data() const
{
return data_;
}
template<typename T>
Node<T>* Node<T>::link() const
{
return link_;
}
The calling code is
List<string> test;
test.add("abc");
cout << test.locate("abc") << endl;
Without getting neck-deep in your code, I notice several problems.
Firstly,
locate(T n)
should be
locate(const T& n)
This saves a possible copy of n
And to ask a stupid question, are you sure you've done:
#include <string>
Try :
if( n.compare(p->data()) == 0 )
string::compare documentation
As the comments below have noted, operator== should work. Please double check that you have
#include <string>
using std::string;
The reference to std::istreambuf_iterator is peculiar as nothing in the code you show justifies it -- can you please show us Node and whatever other code impinges on this in a minimal failing example? Trying to evince the problem from very partial code and an error message is very much like pulling teeth...!-)
This looks OK, I can't see how the std::istreambuf_iterator gets into the picture...
One thing you may want to adjust is taking const T& instead of T as in-parameters to your methods, e.g.
Node(const T& d, Node<T> * l = NULL);
void data(const T& d);
int List<T>::locate(const T& n) const { ...
What with the actual problem, there's bound to be something else going on.
Start deleting code untill it works again. Some typo or rogue macros or conflicting namespaces screw things up.
Will this compile by itself?
string data = "bla";
Node<string> p("bla");
bool b = p.data() == data;
(Every C++ programmer should make a cout << "bla" << end; typo. Very entertaining)

I cannot compile using template in C++

I compiled the following cords with g++
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Node<const char*>{
private:
string x_;
Node* next_;
public:
Node (const char* k, Node* next):next_(next),x_(k){}
string data(){return x_;}
Node *get_next(){return next_;}
};
$ g++ -c node01.cc
node01.cc:5: error: ‘Node’ is not a template
What's wrong?
I'm begginer for c++
You're mixing up declarations and instantiations. When you declare a template, you don't specify a type immediately after its name. Instead, declare it like this:
template<class T>
class Node {
private:
const T x_;
Node *next_;
public:
Node (const T& k, Node *next) : x_(k), next_(next) { }
const T& data(){return x_;}
Node *get_next(){return next_;}
};
Your original declaration also confuses string, const char *, and generic types that should be in terms of T. For a template like this, you probably want to let the user define the type of the member (x_). If you explicitly declare it as const char * or string, you're losing genericity by limiting what the user can use for T.
Notice that I changed the types of the instance variables, the parameters of the constructor and the return type of data() to be in terms of T, too.
When you actually instantiate a variable of the template type, you can provide a concrete type parameter, e.g.:
int main(int argc, const char **argv) {
Node<char*> *tail = new Node<char*>("tail", NULL);
Node<char*> *node = new Node<char*>("node", tail);
// do stuff to mynode and mytail
}
Whenever you write the template name Node outside the template declaration, it's not complete until you provide a value for the parameter T. If you just say Node, the compiler won't know what kind of node you wanted.
The above is a little verbose, so you might also simplify it with a typedef when you actually use it:
typedef Node<char*> StringNode;
int main(int argc, const char **argv) {
StringNode *tail = new StringNode("tail", NULL);
StringNode *node = new StringNode("node", tail);
// do stuff to mynode and mytail
}
Now you've built a linked list of two nodes. You can print out all the values in the list with something like this:
for (StringNode *n = node; n; n = n->get_next()) {
cout << n->data() << endl;
}
If all goes well, this will print out:
node
tail
Your class declaration should look like this:
template<class T>
class Node{
private:
T x_;
Node* next_;
public:
Node (const T& k, Node* next):next_(next),x_(k){}
T data(){return x_;}
Node *get_next(){return next_;}
};
Notice how I removed all references to string or const char * and replaced them with the generic type T. Your class, since it is templated, should not refer to any specific type but should do everything in terms of the generic T type.
The const char * is specified later when you declare a Node variable. Or it could be any other type, not just const char *. The point is, when you're declaring the Node class you just use the generic type T in the code without reference to any specific type. You specify a specific type only when you actually use a Node.
Node<const char *> stringNode("foo", NULL);
Node<int> intNode(5, NULL);
This has allowed us to have a single definition of the Node class but be able to use it to create both nodes where the data is a string and nodes where the data is an integer. Hooray templating!