Edit: Reformatting the entire question
Making a Linked List lib, and I wanted to pass through multiple values in order to make the appending of items easier, so I created some Variadic Functions, which while testing with int values, worked well, but not for other data types.
My Linked List Code:
#include<bits/stdc++.h>
using namespace std;
template<typename data_type>
struct _node {
data_type data{};
_node<data_type>* link = nullptr;
_node(data_type value) : data(value) {}
};
template<typename s_data_type>
struct linked_list {
private:
typedef _node<s_data_type> node;
typedef s_data_type dt;
int _size{};
node* head = nullptr;
node* last = nullptr;
public:
template<typename ...Args> linked_list(Args ...arg) {
(append(arg), ...);
}
template<typename ...Args> void append(Args ...arg) {
(append(arg), ...);
}
void append(const dt value) {
if (this->head == nullptr) {
head = new node(value);
last = head;
}
else {
last->link = new node(value);
last = last->link;
}
_size++;
}
//Methods, Constructors, etc...
};
int main(){
linked_list<string> list("123", "Such a", "Why does this work");
list.print();
list.append("hmm");
list.append("wooowowow", "Please Work");
list.append("No");
println();
list.print();
return 0;
}
Now, in order to append the list, I have a append
function,which works fine by itself for tested data types Float
, Int
, String
, and also the variadic functions as long as the intiallized LL is of int
type.
The first variadic constructor, works well, doesn't throw any Segmentation errors, it's the overloaded append
func which throws Segmentation faults, but it all works for Int type, which is because int is a structural class type for templates I guess? Probably not.
If Main function is written for linked_list<int>
:
linked_list<int> list(1, 2, 3);
list.append(4, 5);
list.print();
Output:
{ 1 2 3 4 5 }
But for linked_list<string>
, the variadic function append
gives me a Segmentation Fault, which even after looking into it, I can't pinpoint why?
Segmentation Fault
Exception has occurred.: Segmentation fault
Now I have looked into parameter folds, unary, binary stuff with folding parameters, read some docs and forums, and I came up with the following code, which I can barely understand why it works.
template<typename ...args> void append(dt val, args ...arg) {
(append(val), ((arg), ...));
}
And for the String LL initialization it produces:
{ 123 Such a Why does this work }
{ 123 Such a Why does this work hmm wooowowow No }
It skips on the "Please Work" string, and I don't know why, or even how it works TBH, but yeah, it works, barely? And for the Int section, same, doesn't append the 5 to the LL.
{ 1 2 3 4 }
My Expectations were:
For String:
{ 123 Such a Why does this work }
{ 123 Such a Why does this work hmm wooowowow Please Work No }
For Int:
{ 1 2 3 4 5 }
1 2 3 4 5
After inserting std::cout to every function, it printed a lot of lines, I found your code crashed on:
list.append_values("hmm");
The variadic append function is inf recursive.
Too many recursive function call -> stack overflow -> segmentation fault.
Rename at least one of the append
function to distinguish them.
#include <iostream>
template<typename data_type>
struct _node {
data_type data{};
_node<data_type>* link = nullptr;
_node(data_type value) : data(value) {}
};
template<typename s_data_type>
struct linked_list {
private:
typedef _node<s_data_type> node;
typedef s_data_type dt;
int _size{};
node* head = nullptr;
node* last = nullptr;
public:
template<typename ...Args> linked_list(Args ...arg) {
(append_value(arg), ...);
}
void append_value(const dt value) {
if (this->head == nullptr) {
head = new node(value);
last = head;
}
else {
last->link = new node(value);
last = last->link;
}
_size++;
}
template<typename ...Args> void append_values(Args ...arg) {
(append_value(arg), ...);
}
void println() {
node* current = head;
while (current != nullptr) {
std::cout << current->data << " -> ";
current = current->link;
}
std::cout << "nullptr" << std::endl;
}
};
void println() {
std::cout << std::endl;
}
int main() {
linked_list<std::string> list("123", "Such a", "Why does this work");
list.println();
list.append_values("hmm");
list.append_values("wooowowow", "Please Work");
list.append_values("No");
println();
list.println();
return 0;
}
Use enable_if<bool, class> to conditionally enable templates.
#include <type_traits>
template<typename ...Args>
typename std::enable_if<(sizeof...(Args) > 1), void>::type append(Args ...arg) {
(append(arg), ...);
}