The instantiation of the template class is wrong - c++

The g++ compiler prompt the following statement is wrong:
template<typename Type>
class SingleList{
public:
SingleList()
{
head = new SingleListNode<Type> () ; //Error happens here!!!
}
The error message is :
./inc/single_list.h: In instantiation of ‘SingleListNode<int>’:
./inc/single_list.h|39 col 13| instantiated from ‘SingleList<Type>::SingleList() [with Type = int]’
The definition of head is the following, maybe problem is not related here.
SingleListNode<Type> *head;
The instantiation of class SingleList in main function is :
int main()
{
SingleList<int> list;
I don't know where the syntax error happens, can anyone help me? Thanks!!
========================================================================
The following is the content of source file:
template<typename Type> class SingleList;
template<typename Type> class SingleListNode{
private:
friend class SingleList<Type>;
SingleListNode() : next(NULL){}
public:
friend ostream& operator<< <Type>(ostream& os,SingleListNode<Type>& sln); //Error here!!
private:
SingleListNode *next;
};
template<typename Type> ostream& operator<<(ostream& os,SingleListNode<Type>& out){
os<<out.data;
return os;
}
template<typename Type> class SingleList{
public:
SingleList()
{
head = new SingleListNode<Type> () ; //Error happens here.
}
~SingleList(){
delete head; //Same error
}
private:
SingleListNode<Type> *head;
};
The error message prompted by g++
|| g++ -g -I ./inc/ -c single_list_test.cpp -o single_list_test.o
|| single_list.h: In instantiation of ‘SingleListNode<int>’:
single_list.h|25 col 13| instantiated from ‘SingleList<Type>::SingleList() [with Type = int]’
single_list_test.cpp|9 col 18| instantiated from here
single_list.h|10 col 18| error: template-id ‘operator<< <int>’ for ‘std::ostream& operator<<(std::ostream&, SingleListNode<int>&)’ does not match any template declaration
|| make: *** [single_list_test.o] Error 1

To my gcc , just modify the following statement
friend ostream& operator<< <Type>(ostream& os,SingleListNode<Type>& sln)
to
friend ostream& operator<< (ostream& os,SingleListNode<Type>& sln)

Related

Failed implicit conversion from Object<T> to Object<const T>

As practice I tried to make a wrapper around raw pointers to have cleaner memory management when using CUDA. Basically I made a PointerBase template that has a PointerBase specialization for const pointers. This template is the base template for a HostPointer and a DevicePointer template that manage memory on CPU side and GPU side respectively (but this is out of scope of this question). I struggle with the conversion from a PointerBase<T> object into the PointerBase<const T> specialization.
(Keep in mind this is more about practicing C++ templates than production use).
Here is a simple code demonstrating the behavior.
template <typename T>
struct Pointer
{
T* ptr_;
Pointer() = default;
Pointer<T>& operator=(const Pointer<T>& other) = default;
operator Pointer<const T>() const { return Pointer<const T>(ptr_); }
T* get() const { return ptr_; }
};
template <typename T>
struct Pointer<const T>
{
const T* ptr_;
Pointer() = default;
Pointer<const T>& operator=(const Pointer<const T>& other) = default;
const T* get() const { return ptr_; }
};
template <typename T>
T dereference(Pointer<const T> data)
{
return *data.get();
}
int main()
{
int value = 7.0;
Pointer<int> ptr{&value};
//int tmp3 = dereference(ptr); // not compiling
int tmp4 = dereference(Pointer<const int>(ptr)); // compiling
return 0;
}
This code fails to compile with the following error (gcc 8.4.0 on ubuntu 20.4, with c++14 standard)
main.cpp: In function ‘int main()’:
main.cpp:41:31: error: no matching function for call to ‘dereference(Pointer<int>&)’
int tmp3 = dereference(ptr); // not compiling
^
main.cpp:32:3: note: candidate: ‘template<class T> T dereference(Pointer<const T>)’
T dereference(Pointer<const T> data)
^~~~~~~~~~~
main.cpp:32:3: note: template argument deduction/substitution failed:
main.cpp:41:31: note: types ‘const T’ and ‘int’ have incompatible cv-qualifiers
int tmp3 = dereference(ptr); // not compiling
^
Why is the conversion operator not considered for calling the dereference function ?
I feel there is a connection to the fact that the Pointer<const T> type is a specialization of the Pointer template. But I still don't understand why a conversion is not happening.
I get the same result when defining a constructor in Pointer<const T> taking a Pointer<T> as a parameter.
Any help ?
PS : Interestingly, I get the same behavior with std::shared_ptr.
#include <memory>
template <typename T>
T dereference(std::shared_ptr<const T> data)
{
return *data.get();
}
int main()
{
std::shared_ptr<int> sptr(new int[10]);
int tmp1 = dereference(sptr); // not compiling
//int tmp2 = dereference(std::shared_ptr<const int>(sptr)); //compiling
return 0;
}
main.cpp: In function ‘int main()’:
main.cpp:9:32: error: no matching function for call to ‘dereference(std::shared_ptr<int>&)’
int tmp1 = dereference(sptr); // not compiling
^
main.cpp:4:3: note: candidate: ‘template<class T> T dereference(std::shared_ptr<const _Tp>)’
T dereference(std::shared_ptr<const T> data) { return *data.get(); }
^~~~~~~~~~~
main.cpp:4:3: note: template argument deduction/substitution failed:
main.cpp:9:32: note: types ‘const _Tp’ and ‘int’ have incompatible cv-qualifiers
int tmp1 = dereference(sptr); // not compiling
^

friend method from a template specializated struct: g++ and clang++ different behaviour

Trying to propose a solution to another question, I bumped (again) my nose against code that compile and work with clang++ (3.5) but give compilation error with g++ (4.9.2)
The following is a simplified minimal (I hope) example
#include <iostream>
class foo;
template <std::size_t>
struct bar;
template <>
struct bar<0U>
{ static void baz (foo const & f); };
class foo
{
int i = 42;
template <std::size_t I>
friend void bar<I>::baz (foo const &);
};
void bar<0U>::baz (foo const & f)
{ std::cout << f.i << std::endl; }
int main()
{
foo f;
bar<0U>::baz(f);
}
The error from my g++ is
test_114-98,11,14,clang.cpp:18:41: error: member ‘void bar<<anonymous> >::baz(const foo&)’ declared as friend before type ‘bar<<anonymous> >’ defined
friend void bar<I>::baz (foo const &);
^
test_114-98,11,14,clang.cpp: In static member function ‘static void bar<0ul>::baz(const foo&)’:
test_114-98,11,14,clang.cpp:15:13: error: ‘int foo::i’ is private
int i = 42;
^
test_114-98,11,14,clang.cpp:22:19: error: within this context
{ std::cout << f.i << std::endl; }
^
My question, as usual, is: who's right and who's wrong.

C++11 init templated member variable

I want to have templated member variable, inited with constructor, like this:
struct S{
//typedef S ThisT;
template<class IdsT, class DataT>
struct CallbackPack{
/*constexpr */CallbackPack(IdsT &selfIds):
selfIds(selfIds){}
const IdsT &selfIds;
};
const CallbackPack<S, S> callbackPack123 = CallbackPack<S, S>((*this));
};
But when I try to compile this I get error.
g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:16:65: error: expected ';' at end of member declaration
const CallbackPack<S, S> callbackPack123 = CallbackPack<S, S>((*this));
^
main.cpp:16:66: error: expected unqualified-id before '>' token
const CallbackPack<S, S> callbackPack123 = CallbackPack<S, S>((*this));
^
main.cpp:16:65: warning: non-static const member 'const S::CallbackPack<S, S> S::S' in class without a constructor [-Wuninitialized]
const CallbackPack<S, S> callbackPack123 = CallbackPack<S, S>((*this));
^
main.cpp:16:62: error: wrong number of template arguments (1, should be 2)
const CallbackPack<S, S> callbackPack123 = CallbackPack<S, S>((*this));
^
main.cpp:9:12: error: provided for 'template<class IdsT, class DataT> struct S::CallbackPack'
struct CallbackPack{
^
http://coliru.stacked-crooked.com/a/ea9ed4482306ce17
As Mooing Duck said, this is compiler bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52595.
To avoid it, you should add parentheses:
const CallbackPack<S, S> callbackPack123 = (CallbackPack<S, S>(*this));
EDIT:
If I'm understanding what you want right, try out this code:
#include <iostream>
#include <tuple>
#include <functional>
struct S{
S() : callbackPack123(*this) {}
template<class IdsT, class DataT>
struct CallbackPack{
// Initializing reference with nullptr is NOT A GOOD THING.
// I'm just doing it to prove that no default constructors are called.
CallbackPack() : selfIds_(nullptr) {
std::cout << "EMPTY CONSTRUCTOR CALLED\n";
}
CallbackPack(IdsT &selfIds) : selfIds_(selfIds) {
std::cout << "IdsT CONSTRUCTOR CALLED\n";
}
const IdsT &selfIds_;
};
const CallbackPack<S, S> callbackPack123;
};
int main()
{
S s;
return 0;
}
It prints
IdsT CONSTRUCTOR CALLED
and nothing else, indicating that the member has been created with the IdsT constructor. I hope this answers your question.

Count.h:10:5: error: ISO C++ forbids declaration of 'T' with no type [-fpermissive] T(); ^

I'm having trouble compiling my first project using template classes, getting errors all stemming from my template classes, including:
In file included from CountArray.h:1:0,
from Executive.h:2,
from main.cpp:3:
Count.h:10:5: error: ISO C++ forbids declaration of 'T' with no type [-fpermissive]
T();
^
Count.h:10:3: error: declaration of 'int Count<T>::T()'
T();
^
Count.h:4:11: error: shadows template parm 'class T'
template <typename T>
^
Count.h:11:4: error: typedef-name 'T' used as destructor declarator
~T();
^
Count.h:11:6: error: declaration of '~T' as member of 'Count<T>'
~T();
^
Count.h:12:3: error: 'T' does not name a type
T getItem();
^
And others from the like. I have two template classes,
template <typename T>
Count<T>::T(){
item=new Count<T>;
count=1;
}
template <typename T>
Count<T>::~T(){
delete item;
}
template <typename T>
//needs type declaration, error for it being T type
T Count<T>::getItem(){
return item;
}
template<typename T>
void Count<T>::setCount(){
count++;
}
template <typename T>
int Count<T>::getCount(){
return count;
}
and another which has the header file
#include "Count.h"
#ifndef COUNTARRAY_H
#define COUNTARRAY_H
template <typename T>
class CountArray{
private:
Count<T>* array;
int arraySize; // initially: 10
int numItemsStored=0;
public:
CountArray();
CountArray(const CountArray<T>& countArr);
~CountArray();
void bumpCount(T t);
int getNumItemsStored() const;
Count<T> getItem(int whichItem) const;
int getCount(int whichItem) const;
void print();
int setArraySize(int size);
int getArraySize();
void doubleArraySize();
};
#include "CountArray.cpp"
#endif
Which has instances called by Executive:
#include <fstream>
#include "CountArray.h"
class Executive{
private:
CountArray<char> charArray;
CountArray<int> intArray;
CountArray<std::string> strArray;
template <typename T>
static void print(CountArray<T> arr); // arr MUST be passed by value
template <typename T>
static void read(std::istream& is, CountArray<T>& arr);
public:
Executive(std::istream& charFile, std::istream& intFile,
std::istream& stringFile);
void print() const;
};
and then the main file:
#include <iostream>
#include <fstream>
#include "Executive.h"
//Get file names
int main(int argc, char* argv[]){
std::ifstream charFin, intFin, stringFin;
//open file, check if open, then continue if so.
charFin.open(argv[1]);
if(charFin.is_open()){
argv[1].read(charFin, charArray);
}
else{
std::cout <<"Unable to open " <<argv[1] <<std::endl;
return -1;
}
intFin.open(argv[2]);
if(intFin.is_open()){
argv[2].read(intFin, intArray);
}
else{
std::cout <<"Unable to open " <<argv[2] <<std::endl;
return -1;
}
stringFin.open(argv[3]);
if(stringFin.is_open()){
argv[3].read(stringFin, strArray);
}
else{
std::cout <<"Unable to open " <<argv[3] <<std::endl;
return -1;
}
Executive exec(charFin, intFin, stringFin);
exec.print();
return 0;
}
I don't know where or how to fix these errors, but I know they're related to the templates and I understand this is a very narrow-seeming question but I hope it can help others having similar errors, seeing as they all have the same rooting problem.
template <typename T>
Count<T>::T(){
item=new Count<T>;
count=1;
}
should be
template <typename T>
Count<T>::Count(){
item=new Count<T>;
count=1;
}
etc.

ToString for templated linked list?

Here's my code:
template<typename T>
class list {
private:
node<T>* head;
node<T>* tail;
int len;
public:
list(){
this->len = 0;
this->head = this->tail = 0;
}
~list(){
node<T>* n = this->head;
if (!n) return;
node<T>* t = NULL;
while (n){
t = n->next;
delete n;
n = t;
}
}
/* other stuff */
ostream& operator<<(ostream &o, const list<T>& l) {
node<T>* t = l.head;
while (t){
strm << *(t->value);
if (!t->next) break;
strm << ", ";
t = t->next;
}
return strm;
}
};
I get the following compile error:
rm bin *.o -f
g++ -g -Wall main.cpp -o bin
main.cpp:110: error: 'std::ostream& list<T>::operator<<(std::ostream&, const list<T>&)' must take exactly one argumentmain.cpp: In function 'int main(int, char**)':
main.cpp:151: error: no match for 'operator<<' in 'std::cout << l'
/usr/include/c++/4.4/ostream:108: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
... other errors
make: *** [main] Error 1
So, here's my question. What do I need to do to make this work? I was trying to follow this question as an example.
Your operator<< is declared as a member function. You need to make it a free function instead, i.e. define it outside the class:
template <class T>
class list {
// ...
};
template <class T>
ostream& operator<<(ostream &o, const list<T>& l)
{
// ...
};
If you need to make your operator<< a friend of the class then please have a look at my answer to this question
Also, I noticed that you're using ostream without std::, implying that you're using using namespace std.
If you're doing that, then it's a really bad idea to call your class list, since there is a std::list that will be pulled into scope by using namespace std if #include <list> is added to the file at any time in the future.
Can you try to make the operator<< function as friend?
....;
friend ostream& operator<<(ostream &o, const list<T>& l) {
....;
This is because as shown in the other question, this function has to be declared as a free function, if declared as a member of list, it is only used if it is actually called on a list object itself.
Edit
Good catch by #je4d.
Looking at your code it looks like you dont need the operator to be a friend since im guessing you will have accessors for head and tail. It would be easier to just declare and define it outside the class as a templated free function.
I ended up using a combination of boost::lexical_cast<std::string> and the suggested ostream& operator << method.