This question already has answers here:
Derived template-class access to base-class member-data
(3 answers)
Closed 5 years ago.
I have created a variable in base class that is a vector of template but I'm not able to access this member from the derived class , can someone explain?
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
/*
*
*/
template <typename T>
class Apple{
protected:
public:
vector<T> vec;
virtual void foo(T node) =0;
};
template <typename T>
class Ball:public Apple<T>{
public:
void foo(T node){
cout<<"hahaha\n";
vec.push_back(node);/* I GET COMPILATION ERROR HERE"vec was not declared in this scope"*/
}
};
int main(int argc, char** argv) {
Ball<int> b;
b.foo(10);
return 0;
}
The member vec is of a template parameter dependent type so the compiler needs some help like:
this->vec.push_back(node);
or use qualified name:
Apple<T>::vec.push_back(node)
Thanks to #Avran Borborah - Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
Here’s the rule: the compiler does not look in dependent base classes (like B<T>) when looking up nondependent names (like f).
This doesn’t mean that inheritance doesn’t work. ...
You have not created any private members in the base class.
To resolve the error, you can replace the line which produces compilation error with :
Apple::vec.push_back(node);
or
this->vec.push_back(node)
Related
Let's say I have following templated C++ class
#include <cstdint>
template <uint32_t NO_POINTS>
class A
{
public:
struct Point
{
float x;
float y;
};
A(const Point (&points)[NO_POINTS])
{
for (uint32_t point = 0; point < NO_POINTS; point++) {
table[point] = points[point];
}
}
private:
Point table[NO_POINTS];
};
and I would like to use an instance of this class as a private member of the following class:
#include "A.h"
template <uint32_t NO_LUT_POINTS>
class B
{
public:
B(A<NO_LUT_POINTS>::Point (&table)[NO_LUT_POINTS]) : lut(table){}
private:
A<NO_LUT_POINTS> lut;
};
#include "B.h"
int main(int argc, char** argv) {
B<4> foo({{1326.0, 25.0}, {1601.0, 30.0}, {1922.0, 35.0}, {2293.0, 40.0}});
return 0;
}
I have attempted to compile this code but the compiler reports following error
A<NO_LUT_POINTS>::Point is not a type. I don't understand what the reason for this error is. Can anybody explain to me why the compiler reports this error?
This is a common mistake with types nested in template classes. You need to add typename to tell the compiler that Point is a type.
...
public:
B(typename A<NO_LUT_POINTS>::Point const (&table)[NO_LUT_POINTS]) : lut(table){}
...
Beyond solving your problem, however, please notice that Point doesn't depend on the template parameters of A, so you should not nest it in that class. This would remove the necessity for adding typename.
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 1 year ago.
Template member functions allow us to parameterise functions independently for a class they belong to. They are supported for both template and non-template classes and it worked fine if we directly call it from class object.
But in case if class is composed-off in other class c++ compiler fail to resolve it. In my case I am able to call template member function directly from object but it fails( MsgParser::run(){source.showType();}) when object is composition. logic behind it ?
struct A{};
struct B{};
class DataSource{
public:
template<class Type>
void showType(){
std::cout<<std::endl<<typeid(Type).name();
}
void disp(){ std::cout<<std::endl<<"All OK";}
private:
};
template<class Source>
class MsgParser{
public:
MsgParser(Source &s):source(s){}
void run(){
source.disp();
source.showType<A>(); // failed to call ??
}
private:
Source &source;
};
int main()
{
DataSource dataSource;
dataSource.showType<A>();
MsgParser<DataSource> msgParser(dataSource);
msgParser.run();
return 1;
}
Something like
source.showType < A > (b);
is ambigious to the compiler not knowing yet what kind of template argument you will pass to it. It might as well be a class member showType inside source that is compared to A and b. Therefore you will have to add .template to the call of showType to distinguish it from a comparison
source. template showType<A>();
Try it here!
If you are interested in when to add typename and template refer to this lengthy explanation.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
I've got a class that uses a two-arguments template:
template<class T, class R>
When I try to declare an object in main.cpp it says: "undefined reference to FileTest<int, int>::FileTest()
Here's the code:
FileTest.h
#ifndef FILETEST_H
#define FILETEST_H
#include <string>
#include <iostream>
....
using namespace std;
template<class T, class R>
class FileTest : public FileInput , FileOutput
{
public:
FileTest();
FileTest(const string nome_file):FileInput(nome_file),FileOutput(nome_file){
};
virtual ~FileTest();
void setNewEntry(const T id_domanda,const R id_risposta);
...
private:
...
};
template<class T, class R>
FileTest<T,R>::~FileTest()
{
//dtor
}
template<class T, class R>
void FileTest<T, R>::setNewEntry(const T id_domanda,const R id_risposta){
/*
sets new entry in a vector
*/
}
#endif // FILETEST_H
main.cpp
#include <iostream>
#include "FileTest.h"
using namespace std;
int main()
{
FileTest<int, int> object;
return 0;
}
Error (in main.cpp) :
undefined reference to FileTest<int, int>::FileTest()
When I try with another class which has only one template argument, everything is working! What's the cause of this error?
You declared a zero parameter constructor for FileTest:
template<class T, class R>
class FileTest : public FileInput , FileOutput
{
public:
FileTest();
But I can't see an implementation for that method anywhere. As this is a constructor for a template class, its implementation should be in the header file somewhere.
Problem
You have declared constructor without parameters
FileTest();
but didnt provide his definition anywhere, so linker won't find it and this will result in "undefined reference to" if you would attempt to call this function.
This constructor without paramters is called when constructing object in main FileTest<int, int> object;)
Fix
Change constructor to
FileTest() {}
or
FileTest() = default;
This question already has answers here:
templates: parent class member variables not visible in inherited class
(3 answers)
Closed 8 years ago.
When I compile the following templated C++ code with GCC 4.8.3
template <typename dtype> class Base {
public:
dtype base;
dtype ceiling;
Base() { };
virtual ~Base() { };
};
template<typename dtype> class Building : public Base<dtype> {
public:
dtype wall;
Building(dtype concrete) {
Base<dtype>::base=concrete;
ceiling=concrete;
wall=concrete;
};
~Building() { };
};
int main (int argc, char* argv[]) {
Building<float>* building=new Building<float>(2.0);
std::cout << building->base << std::endl;
}
I get the error
error: ‘ceiling’ was not declared in this scope
ceiling=concrete;
So it appears that
Base<dtype>::base=concrete;
works, but
ceiling=concrete;
does not. Is there any way I can mogrify this templated code so that, in the derived class constructor I can just reference "ceiling" from the templated base class without having to clarify which class it is from?
Thanks in advance
You can use this->ceiling.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
Please read this first:
Storing C++ template function definitions in a .CPP file
This is what I am attemptng here.
I used the first method from this site to define a template class in a cpp file:
http://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp
It looks like this:
b.h :
#ifndef B_H_
#define B_H_
class B
{
public:
B();
};
#endif
a.h :
#ifndef A_H_
#define A_H_
template<class T>
class A
{
public:
A();
int get();
private:
int val;
};
#endif
a.cpp
#include "a.h"
template <class T>
A<T>::A()
{
}
template <class T>
int A<T>::get()
{
return 42;
}
// No need to call this TemporaryFunction() function,
// it's just to avoid link error.
void TemporaryFunction ()
{
TestTemp<B> TempObj;
}
main.cpp
#include "a.h"
int main(int argc, char** argv){
A<B> ab;
ab.get();
}
I have to change get to virtual or I get:
undefined reference to `A::get()'
I don't understand this.
This is just a sample of the real code (that is too large). If it does not reproduce, I will provide more details tomorrow.
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)
Template members are either explicitly instantiated or instantiated on demand. You are not explicitly instantiating the template, but rather causing the implicit instantiation of the type and the constructor by means of the local variable. Since you don't use A<B>::get() that function will not be instantiated by the compiler.
If the function is marked as virtual, then it is odr-used just by means of instantiating the object (hint: the address of each virtual function, or a similar piece of information, needs to be stored in the vtable).
That being said, and without reading the article in question, this approach is wrong. You don't need to create the function and cause the instantiation of each member function, but rather use explicit instantiation of the template.
template class A<B>; // Explicit instantiation