Inheriting protected fields in template derived class of template class [duplicate] - c++

This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Derived template-class access to base-class member-data
(3 answers)
Using member variables inherited from a templated base class (C++)
(1 answer)
Closed 3 years ago.
I'm having issues with accessing protected members in template subclasses of a template class.
Thing is, if I remove the templates, everything works fine. I know how to work around my problem in an ugly way, by simply writing "using Base::my_protected_member" for every single derived class. But why should I need to do that in the first place ?
Here's a minimal commented example
template<class T>
class Base
{
protected:
T x;
public:
Base(T x) : x(x) {}
};
template<class T>
class Derived : public Base<T>
{
//using Base<T>::x; //why ?!
public:
Derived(T x);
void print();
};
template<class T>
Derived<T>::Derived(T x) : Base<T>(x)
{ cout << x << endl; } //works fine
template<class T>
void Derived<T>::print() { cout << x << endl; } //doesn't work
int main()
{
Derived<int> d(4);
d.print();
}
I don't quite understand what's going on, or how to work around this in a nice way. probably I'm doing something wrong...

Related

C++ why is `this` necessary? [duplicate]

This question already has answers here:
Derived template-class access to base-class member-data
(3 answers)
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 10 months ago.
With GCC, we can't access the member in the base class without writing this explicitly, but it works on MSVC, what is going on? Is it because of the CRTP?
#include <iostream>
template<class T>
struct Base {
protected:
T* a;
};
template<class U>
struct Derived : Base<Derived<U>> {
void print_a() {
std::cout << a << std::endl; // doesn't work on GCC
std::cout << this->a << std::endl; // works on GCC
}
};
int main() {
Derived<float> d;
d.print_a();
}

C++ derived template class is inheriting from template base class, cannot call base class constructor [duplicate]

This question already has answers here:
How to call constructor of a template base class in a template derived class?
(2 answers)
Closed 10 months ago.
i am trying to inherit from base class which is template, the derived class is also template, they have same type T. I am getting compile error: illegal member initialization: 'Base' is not a base or member...
Why? How can i call the base class constructor?
#include <iostream>
template<class T>
class Base {
public:
Base(T a) {
std::cout << "A: " << a << std::endl;
}
};
template<class T>
class Derived : public Base<T> {
public:
Derived(T a) :
Base(a) // this is the problem
{}
};
int main() {
int a = 1;
Derived<int> derived(a);
}
Since Base is a template, you need to specify the template parameter in the member initializer list:
Derived(T a) : Base<T>(a) {}
// ^^^

Why in c++, a derived class template publicly Inherited from base class template can't call the base class' funtion directly? [duplicate]

This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Accessing public inherited Template data members [duplicate]
(1 answer)
Closed 2 years ago.
This is the code:
class A : public std::vector<int>
{
public:
void fooA()
{
std::cout << "A::fooA() + " << size() << '\n';
}
};
template <typename T>
class B : std::vector<T>
{
public:
void fooB()
{
std::cout << "B::fooB() + " << size() << '\n';
}
};
Class A is correct.
But in class B, size() is considered undeclared, unless I change it to std::vector<T>::size()
Why doesn't class A have to add std::vector<int>, but does class B have to?

Overloading template operator in derived class [duplicate]

This question already has an answer here:
SFINAE method completely disables base class's template method in clang
(1 answer)
Closed 3 years ago.
Given a base class and a derived class, which both provide conditionally enabled operators for specific parameter types using SFINAE:
#include <type_traits>
class Base
{
public:
template<class T, std::enable_if_t<std::is_scalar_v<T>>* = nullptr>
void operator>>(T& value) {
}
};
class Derived: public Base
{
public:
using Base::operator>>;
template<class T, std::enable_if_t<!std::is_scalar_v<T>>* = nullptr>
void operator>>(T& value) {
}
};
int main(int argc, char *argv[])
{
int foo;
Base base;
base >> foo; // this works
Derived derived;
derived >> foo; // this doesn't work, the operator from the base class is not considered
}
then calling an operator defined in the base class on an instance of the derived class will not work, even though it should have been made visible by the appropriate using Base::operator>>; declaration. Why? How can the operator from the base class be made usable without verbosely repeating the declaration/definition?
The problem does not occur if the operator in question is not a template in the base class.
Edit: Tested with msvc 15.9.7 as well as clang.
I think the problem here is that a using declaration only brings the declarations of functions and function templates into a derived class that have signatures which are not overridden by members of the derived class [namespace.udecl]/15. So this code should indeed not compile.
Use free functions instead of class members to fix the problem:
#include <type_traits>
class Base
{
public:
template<class T, std::enable_if_t<std::is_scalar_v<T>>* = nullptr>
friend void operator>>(Base&, T& value) {
}
};
class Derived: public Base
{
public:
template<class T, std::enable_if_t<!std::is_scalar_v<T>>* = nullptr>
friend void operator>>(Derived&, T& value) {
}
};
int main()
{
int foo;
Base base;
base >> foo;
Derived derived;
derived >> foo;
}
live example here

Member from base class template not found [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I have to access template base class members through the this pointer?
I have a class hierarchy like the following:
template<typename T>
class Base {
protected:
T t;
};
template<typename T>
class Derived: public Base<T> {
public:
T get() { return t; }
};
int main() {
Derived<int> d;
d.get();
}
The problem is that the protected member variable t is not found in the Base class. Compiler output:
prog.cpp: In member function 'T Derived<T>::get()':
prog.cpp:10:22: error: 't' was not declared in this scope
Is that correct compiler behavior or just a compiler bug? If it is correct, why is it so? What is the best workaround?
Using fully qualified name works, but it seems to be unnecessarily verbose:
T get() { return Base<T>::t; }
To use members from template base classes, you have to prefix with this->.
template<typename T>
class Derived: public Base<T> {
public:
T get() { return this->t; }
};