c++: inherit from instantiated template class fail to compile: cannot find members - c++

I've got the following code:
struct My {
int id;
int value;
};
template < class T >
class IsElement : public T {
protected:
IsElement<T>* the_next;
};
struct elem : public IsElement<My> {
elem(int i, int v) : id(i), value(v), the_next(nullptr) {
}
};
int main() {
return 0;
}
gcc 8.1 failed to compile it, and gives error:
<source>: In constructor 'elem::elem(int, int)':
<source>:13:26: error: class 'elem' does not have any field named 'id'
elem(int i, int v) : id(i), value(v), the_next(nullptr) {
^~
<source>:13:33: error: class 'elem' does not have any field named 'value'
elem(int i, int v) : id(i), value(v), the_next(nullptr) {
^~~~~
<source>:13:43: error: class 'elem' does not have any field named 'the_next'
elem(int i, int v) : id(i), value(v), the_next(nullptr) {
^~~~~~~~
Execution build compiler returned: 1
I think all members are available to be accessed, why can't find "field name"? How to fix it?

Even though you have not implemented it, the base class has a constructor, a default constructor. When the default constructor is called the variables are allocated and initialized. You cannot initialize base class variables in the initialize list, as the base class is not yet created. You can create a constructor in base class and call that in the initialize list.
struct My {
public:
int id;
int value;
};
template < class T >
class IsElement : public T {
public:
IsElement(IsElement<T> * p) : the_next(p) {}
protected:
IsElement<T>* the_next;
};
struct elem : public IsElement<My> {
elem(int i, int v) : IsElement(nullptr) {
id = i,
value = v;
}
};
int main() {
elem e1(0, 0);
return 0;
}
Another way without introducing constructor in template class:
struct My {
public:
int id;
int value;
};
template < class T >
class IsElement : public T {
public:
//IsElement(IsElement<T> * p) : the_next(p) {}
protected:
IsElement<T>* the_next;
};
struct elem : public IsElement<My> {
elem(int i, int v) {
id = i,
value = v;
the_next = nullptr;
}
};
int main() {
elem e1(0, 0);
return 0;
}
You can also call constructor explicitly in the code block of derived class constructor.
elem(int i, int v) :IsElement(nullptr) {
IsElement(nullptr);
the_next = nullptr;
id = i,
value = v;
}

Related

C++: Is it possible to use base class reference variables in a derived class?

I want to use references from the base class without initializing them in the derived class. Is that possible? If so, how?
The example code below generates an error, i.e.line 28: error #368: "Base::Base()" provides no initializer for: reference member "Base::BaseVar1" reference member "Base::BaseVar2"
#include <stdio.h>
class Base
{
protected:
int & BaseVar1;
int & BaseVar2;
public:
Base() = default;
Base(int & BaseVar1, int & BaseVar2) : BaseVar1(BaseVar1),BaseVar2(BaseVar2){}
virtual void vfunction1(void) = 0;
};
class Derived1: public Base
{
public:
Derived1(int & Derived1Var1): Derived1Var1(Derived1Var1)
{
}
int & Derived1Var1;
void vfunction1()
{
printf("BaseVar1 = \n",BaseVar1);
printf("BaseVar2 = \n",BaseVar2);
printf("Derived1Var1 = \n",Derived1Var1);
}
};
class Derived2: public Base
{
public:
Derived2(int & Derived2Var1): Derived2Var1(Derived2Var1)
{
}
int & Derived2Var1;
void vfunction1()
{
printf("BaseVar1 = \n",BaseVar1);
printf("BaseVar2 = \n",BaseVar2);
printf("Derived2Var1 = \n",Derived2Var1);
}
};
As some commenters mentioned, references have to be initialized (in the class definition or their member definition or in the constructor).
The default constructor of Base does not do that, so it should be removed.
Your derived classes can call the other Base constructor from within the initialization list in their constructors.
#include <cstdio> // C++ variant of stdio.h, which puts symbols in std
using namespace std; // do not use this in headers (in your production projects)
class Base
{
protected:
int& BaseVar1;
int& BaseVar2;
public:
// Base() = default; // removed
Base(int& BaseVar1, int& BaseVar2) : BaseVar1(BaseVar1), BaseVar2(BaseVar2) {}
virtual void vfunction1() = 0;
};
class Derived1: public Base
{
public:
Derived1(int& BaseVar1FromDerived1, int& BaseVar2FromDerived1, int& Derived1Var1) :
Base(BaseVar1FromDerived1, BaseVar2FromDerived1),
Derived1Var1(Derived1Var1)
{
}
int& Derived1Var1;
void vfunction1() override // signify override
{
printf("BaseVar1 = %d\n", BaseVar1); // %d was missing
printf("BaseVar2 = %d\n", BaseVar2); // %d was missing
printf("Derived1Var1 = %d\n", Derived1Var1); // %d was missing
}
};
class Derived2: public Base
{
public:
Derived2(int& BaseVar1FromDerived2, int& BaseVar2FromDerived2, int& Derived2Var1) :
Base(BaseVar1FromDerived2, BaseVar2FromDerived2),
Derived2Var1(Derived2Var1)
{
}
int& Derived2Var1;
void vfunction1() override // signify override
{
printf("BaseVar1 = %d\n", BaseVar1); // %d was missing
printf("BaseVar2 = %d\n", BaseVar2); // %d was missing
printf("Derived2Var1 = %d\n", Derived2Var1); // %d was missing
}
};
int main()
{
int a = 1;
int b = 2;
int c = 3;
Derived2 d2(a, b, c);
d2.vfunction1();
}
Output:
BaseVar1 = 1
BaseVar2 = 2
Derived2Var1 = 3

pass lambda to constructor of member variable

Consider the following classes,
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
public:
B(int x) : _x(x), _a([this]() { return _x; }) {}
private:
int _x;
A<???> _a;
};
I am not sure how to specify the type at ???. std:: function<int()> works, but to my knowledge, this implies virtual function calls (of course, this does not have to be bad, but it would be interesting how to do this properly).
Rather than a lambda, you can use a function object that's roughly equivalent.
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
struct GetX
{
int operator()() const { return _b->_x; }
B * _b;
};
public:
B(int x) : _x(x), _a(GetX{ this }) {}
private:
int _x;
A<GetX> _a;
};

c++ How to create an instance of derived class template

I have base class and a bunch of derived classes (only one here for simplicity). I also have holder class with one of derived classes as a template argument. I want holder object to create an instance of derived class. Here is the code:
class base {
protected:
int value;
public:
base() : value (0) { }
base(int value) : value(value) { }
};
class derived : public base { };
template <class T>
class holder {
public:
holder(T) {}
T create(int value) {
return T(value);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
holder<base*> h(&derived());
derived* d = h.create(1); // error here
}
I get an error error C2440: 'initializing' : cannot convert from 'base *' to 'derived *'. I guess that's because type of variable is holder<base*>, so create method is called with base as template argument. But how do I cast it properly if I have a lot of derived classes?
UPD.
I changed holder::create method so it uses std::remove_pointer but I still get the same compile error.
T create(int value) {
return new (std::remove_pointer<T>::type)(value);
}
You can let holder holds derived type rather than base type, and use boost::any or std::any (c++ 17) to store all the holders.
#include "iostream"
#include "boost/any.hpp"
#include "vector"
class base {
protected:
int value;
public:
base() : value (0) { }
base(int value) : value(value) { }
};
class derived1 : public base {
public:
derived1(int value) : base(value) {};
};
class derived2 : public base {
public:
derived2(int value) : base(value) {};
};
template <class T>
class holder {
public:
holder() {}
T* create(int value) {
return new T(value);
}
};
int main()
{
std::vector<boost::any> list;
holder<derived1> h1;
holder<derived2> h2;
list.push_back(h1);
list.push_back(h2);
derived1* pd1 = boost::any_cast<holder<derived1>>(list[0]).create(1);
derived2* pd2 = boost::any_cast<holder<derived2>>(list[1]).create(2);
}

Why structures in c++ don't need constructor?

I am doing C++ from 2 years or so , I say why we need constructors in class and not in structures , and why we cant do constructor overloading in structure...
why we need constructors in class
We don't.
// Perfectly valid
class Foo
{
public:
int x
};
why we cant do constructor overloading in structure...
We can.
// Look, ma!
struct Bar
{
Bar operator+(const Bar& other);
};
I don't know where you heard these claims but it certainly wasn't from trying it out.
A user-defined type declared with the keyword struct is a class.
The only difference between struct and class in C++ is visibility; a struct defaults to public while a class defaults to private.
Once you get past that initial visibility, however, they are indistinguishable. A struct is a class with default public visibility.
These two pieces of code have exactly the same effect.
struct MyClass {
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
void setI(int i) { m_i = i; }
private:
int m_i;
};
// is exactly the same as
class MyClass {
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
void setI(int i) { m_i = i; }
private:
int m_i;
};
or put another way
class MyClass {
int m_i;
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
};
struct MyClass {
private:
int m_i;
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
};

Creating class/handle only from another class

I need only my mesh class to be able to create these classes, and i would like to not make these classes nested, because of too long qualified name if so. How can i do it best?
struct Handle
{
explicit Handle(int i) : _index(i) {}
bool IsValid() { return _index != NO_HANDLE; }
protected:
enum { NO_HANDLE = -1 };
int _index;
};
// **************************************************************************************
struct HalfEdgeHandle : Handle
{
HalfEdgeHandle(int i) : Handle(i) {}
static HalfEdgeHandle GetInvalid() { return HalfEdgeHandle(NO_HANDLE); }
};
// **************************************************************************************
struct FaceHandle : Handle
{
FaceHandle(int i) : Handle(i) {}
static FaceHandle GetInvalid() { return FaceHandle(NO_HANDLE); }
};
// **************************************************************************************
struct VertexHandle : Handle
{
VertexHandle(int i) : Handle(i) {}
static VertexHandle GetInvalid() { return VertexHandle(NO_HANDLE); }
};
Only invalid handle should be accessible outside, for now i think it can be done by using static variables.
Use friend.
class Factory;
struct Handle
{
protected:
explicit Handle(int i) : _index(i) {}
public:
bool IsValid() { return _index != NO_HANDLE; }
protected:
enum { NO_HANDLE = -1 };
int _index;
friend class Factory; // and so on in Derived classes
};