warning: friend declaration 'void traverse(List<T>)' declares a non-template function [-Wnon-template-friend] - c++11

i have a Node template class in one "Node.cpp" and included in file "List.cpp" and List template class
i have to create a traverse function which is friend to the List class to traverse all the node in a List but facing an error here is my error proner
List Class Decleration
template<typename T>
class List{
private:
Node<T> *headNode;
Node<T> *currentNode;
Node<T> *lastCurrentNode;
int size;
public:
List();
void add(T);
T get();
bool next();
friend void traverse(List<T>); // **there is an issue**
};
Friend function Intialization
template <typename T>
void traverse(List <T>list)
{
Node<T> *savedCurrentNode = new Node<T>();
list.currentNode = list.headNode;
for(int i=1; list.next(); i++)
{
cout << "\n Element " << i << " " << list.get();
}
list.currentNode = savedCurrentNode;
}
i am a bigner and try to implement using templates but stuck into a problem now i have no idea how to solve this

Related

Overloading output operator is not working as intended

I'm trying to overload << to print the protected members of a class as a string, but when I try to use it in another class doing std::cout << player2; I get "0x7f60b0100" as output.
"player2" is an Actor*, so I'm not sure what's happening.
class Actor {
private:
string type;
protected:
int health;
int damage;
vector<MoveType> moves;
public:
Actor(string type, int health): type{ type }, health{ health }{damage=0;}
virtual void Hit(int damage){health = health-damage;}
virtual void Heal(int amount){health=+amount;}
const vector<MoveType>& GetMoves() const {return moves;}
bool IsDead() { return health <= 0; }
friend ostream& operator<<(ostream& out, const Actor& actor){
return (out << "DAMAGE DONE: " << actor.damage << "HEALTH: "<< actor.health);
}
};
As you've said it's a pointer to an Actor instance, so that's what you get printed, the value of this pointer.
You need to derefernce the pointer:
std::cout << *player2;

C++ [Error] invalid use of non-static data member 'Tree::root'

#include<iostream>
using namespace std;
class Node{
public:
Node *lch,*rch;
char data;
Node(char data){
this->data=data;
this->lch=nullptr;
this->rch=nullptr;
}
};
class Tree{
private:
Node *root;
public:
Tree(){
root=nullptr;
}
void Road(char p,Node *T=root);
public:
void init(Node* &T=root){
char data;
cin>>data;
if(data!='#'){
T=new Node(data);
init(T->lch);
init(T->rch);
}
}
};
void Tree::Road(char p,Node *T){
if(!T) return;
Road(p,T->lch);
Road(p,T->rch);
if(T->data==p){
cout<<T->data<<"\t";
p=T->data;
}
}
int main(){
Tree T;
T.init();
T.Road('A');
return 0;
}
In class Tree, if I use "static Node* root", It would work well. So why I must add "static"?
And when I used "static Node* root",I got an new error that " test.cpp :(.rdata$.refptr._ZN4Tree4rootE[.refptr._ZN4Tree4rootE]+0x0): undefined reference to `Tree::root' "
Node *T=root is illegal in a default argument because default arguments do not have access to this. You can use two overloads instead, one with a Node* parameter and one without.
void Road(char p) { Road(p, root); }
void Road(char p, Node* T);

Passing const reference pointer fails to match method signature

The following code passes a const pointer reference to a size() helper function. It only works if I remove the const or the & reference operator from the helper function.
#include <iostream>
using namespace std;
template <typename T>
class Test {
public:
Test();
int size();
void insert(T);
private:
struct Node {
T value;
Node* left;
Node* right;
};
Node* root;
int size(const Node*& node);
};
template <typename T>
Test<T>::Test() { root = nullptr;}
template <typename T>
int Test<T>::size() {return size(root);}
template <typename T>
int Test<T>::size(const Node*& node) {
if (node != nullptr)
return 1 + size(node->left) + size(node->right);
return 0;
}
int main() {
Test<int> t;
cout << "Size: " << t.size() << endl;
}
I get the following compiler errors when I compile this code as C++11:
main.cpp:31:11: error: no matching member function for call to 'size'
return size(root);
^~~~
main.cpp:43:26: note: in instantiation of member function 'Test<int>::size' requested here
cout << "Size: " << t.size() << endl;
^
main.cpp:21:11: note: candidate function not viable: no known conversion from 'Test<int>::Node *' to 'const Test<int>::Node *&' for 1st argument
int size(const Node*& node);
^
main.cpp:10:11: note: candidate function not viable: requires 0 arguments, but 1 was provided
int size();
^
1 error generated.
However, if I simply remove the const or the reference operator (&) from the helper function that size() calls, it compiles and runs exactly as expected.
In other words, either of the following works:
int size(Node*& node);
template <typename T> int Test<T>::size(Node*& node)
int size(const Node* node);
template <typename T> int Test<T>::size(const Node* node)
But this does not:
int size(const Node*& node);
template <typename T> int Test<T>::size(const Node*& node)
The declaration and implementation seem identical in all three cases, so I am having a hard time figuring out why the case with the const reference fails.
If it were legal to pass a pointer to non-const object where a reference to pointer to const object is expected, then it would be possible to violate const correctness. Consider:
const int c = 42;
void f(const int*& p) {
// Make p point to c
p = &c;
}
int* q;
f(q); // hypothetical, doesn't compile
// Now q points to c
*q = 84; // oops, modifying a const object

Pass f(a) and f(a,b) as same slot of template parameter : without require explicit signature passing

I want to pass two functions with different signature into a same slot of class template parameter (one each time).
Ignore the strict syntax, this is what I want :-
void hf1 (int a) { std::cout<< "hf1" <<std::endl; }
void hf2 (int a, int i){ std::cout<< "hf2 "<<i<<std::endl; }
template<hfX> class Collection{
int i_=56;
public: test(){
if( "hfX has 1 param" ){hfX(0);} //call hf1
else {hfX(0,i_);} //call hf2
}
};
int main(){
Collection<&hf1> test1; test1.test(); // print "hf1"
Collection<&hf2> test2; test2.test(); // print "hf2 56"
}
Here is the code that works OK, but its usage is not so convenient :-
template<typename ... AA> using hfX = void(*)(AA ... );
void hf1 (int a) { std::cout<< "hf1" <<std::endl; }
void hf2 (int a, int i) { std::cout<< "hf2 "<<i <<std::endl; }
template <typename Tf, Tf F>
class Collection;
template <typename ... I, hfX<I...> F>
class Collection<hfX<I...>, F>{
public:
int i_=56;
template <std::size_t N = sizeof...(I)>
typename std::enable_if<N == 1U, void>::type test (){
F(0);
}
template <std::size_t N = sizeof...(I)>
typename std::enable_if<N == 2U, void>::type test (){
F(0,i_);
}
};
The usage:-
int main () {
Collection<hfX<int>, hf1> test1; //<--- #A dirty signature
Collection<hfX<int,int>, hf2> test2; //<--- #B dirty signature
test1.test(); // print "hf1"
test2.test(); // print "hf2 56"
}
Live version : https://ideone.com/f20BEk
Question
It would be nice if I can call it without explicit redundant signature.
Collection<hf1> test1; //or &hf
Collection<hf2> test2;
How to improve code (especially around hfX and Collection) to make its usage easier?
I don't know how to make what do you want with functions.
But if you can, instead of functions, accept to use static method in classes or structs (and pass that classes/structs as template argument)...
#include <iostream>
struct sf1
{ static void hf (int a) { std::cout << "hf1" << std::endl; } };
struct sf2
{ static void hf (int a, int i) { std::cout << "hf2 " << i << std::endl; } };
template <typename S>
class Collection
{
private:
int i_ = 56;
public:
template <typename T = S>
decltype(T::hf(0)) test() { S::hf(0); /*call sf1::hf */ }
template <typename T = S>
decltype(T::hf(0, 0)) test() { S::hf(0,i_); /*call sf2::hf */ }
};
int main ()
{
Collection<sf1> test1; test1.test(); // print "hf1"
Collection<sf2> test2; test2.test(); // print "hf2 56"
}

What is the return type of this auto?

With some code left out, elsewhere on SOF there is code that looks like this:
// CRTP Abstract Base class for implementing static subject.
// Example Subclass Usage -- Printing Observer:
class Printer : public Observer<Printer> {
public:
Printer() : timesTriggered_(0) {}
template <typename... Args>
void OnNotify(Pressure<Args...> &subject, EventType event) {
std::cout << "Observer ID: " << this->GetID() << std::endl;
switch (event) {
case EventType::UNKNOWN: {
std::cout << "Unknown Event -- Event #" << timesTriggered_++
<< std::endl;
std::cout << "Pressure: " << subject.GetPressure() << std::endl;
break;
}
default: { break; }
}
}
private:
int timesTriggered_;
};
// CRTP Abstract Base class for implementing static subject.
// Example Subclass Usage -- Pressure Sensor:
template <typename... Obs>
class Pressure : public Subject<Pressure<Obs...>, Obs...> {
public:
typedef Subject<Pressure<Obs...>, Obs...> BaseType;
Pressure(std::tuple<Obs &...> &&observers, int pressure)
: BaseType(std::move(observers)), pressure_(pressure) {}
void Change(int value) {
pressure_ = value;
this->NotifyAll(EventType::UNKNOWN);
}
int GetPressure() const { return pressure_; }
private:
int pressure_;
};
// Binding function for use with MakeSubject
// Arguments: observer objects to observe subject notifications
// Return: tuple of references to observers
template <typename... Obs> std::tuple<Obs &...> BindObservers(Obs &... obs) {
return std::tuple<Obs &...>(obs...);
}
// Creator to ease subject creation
// Template Arguments: Subject subclass type
// Arguments: Result from BindObservers
// Any constructor arguments for Subject subclass
// Return: Subject subclass
// Example Usage:
// auto pressure = MakeSubject<Pressure>(BindObservers(printerObs), initialPressure);
template <template <typename...> class T, typename... Args, typename... Obs>
T<Obs...> MakeSubject(std::tuple<Obs &...> &&obs, Args &&... args) {
return T<Obs...>(std::move(obs), args...);
}
In main.cpp
int main() {
Printer printerObs1;
Printer printerObs2;
const int initialPressure = 1;
auto pressure = MakeSubject<Pressure>(
BindObservers(printerObs1, printerObs2), initialPressure);
pressure.Change(12);
}
I need to break out the BindObservers and the return type of MakeSubject, but I can't correctly figure out what to replace both **auto in the pseudo-code below:**
auto obs = BindObservers(printerObs1, printerObs2);
auto pressure = MakeSubject<Pressure>(obs, initialPressure);
What is the exapanded version return types of both auto above? I need to store the return values in std::vector and AFAIK, I can't say
std::vector<auto> vec
[Although I don't see why not since the compiler can probably figure it out]
You can use std::vector<decltype(pressure)>.
But the type should be Pressure<Printer, Printer>.

Resources