In the example pointers/countingptr.hpp of the book C++ Templates - The Complete Guide members of the derived dependent class CountingPtr are referred to using the this pointer. Why is this necessary in this example?
I'm aware that the this pointer is required in order to name members of a dependent base class template. Surely the this pointer is not required in dependent derived class template also?
I believe it's just a style of the guy who was making this code. Some people prefer putting this-> in front of anything that is related to a class inside that class. That indeed may sometimes be useful if you are doing funny things like:
void foo( int a )
{
this->a = a;
}
or if you just think this increases readability.
However, if you use it too much, it will be a mess:
this->a = this->b * this->c - this->foo( this->d, this->bar() );
It's not needed. Some people use this everywhere.
not required in dependent derived class
In what?
There is no "dependent derived class". The derived class is the derived class.
derived class template
It is a class template, but it is parsed as a class.
Think of it this way:
It is not a class template, just a class (a type). A class template specialisation, but still a class, like a normal class.
Or this way:
The derived class template is instantiated with a "magical lazy type" argument. This lazy type argument suspends the compilation of any expression which depends on it.
Related
I am trying to make my head around CRTP and C++20. Basically, I'd like to have static inheritance that can access the derived type's typedefs and using:
template <typename Derived>
class inherit
{
public:
Derived& underlying()
{
return static_cast<Derived&>(*this);
}
Derived const& underlying() const
{
return static_cast<Derived const&>(*this);
}
};
template <typename Derived>
class tester : public inherit<Derived>
{
public:
using value_type = typename Derived::value_type;
};
class real : public tester<real>
{
public:
using value_type = int;
};
int main()
{
return 0;
}
This, as explained in some other questions on SO is not allowed as of C++14 (answers that I find refer to that standard and to C++11). My understanding is that there is no way in C++17 either (if my compiler is right).
What is the current status with C++20? Are there any better solutions with the upcoming standard?
No, it's still not allowed in C++20. And it will undoubtedly remain not being allowed in C++ so long as the derived class is incomplete until the base class template is finished being instantiated. Which will undoubtedly remain the way things are because what you want would require the compiler to compile the derived class to some degree before instantiating the base class template, and that degree of "look ahead" is just not practical. And can lead to infinite loops or other confused constructs, since derived class member declarations/definitions are expected to be able to access accessible base class declarations.
Consider the simple case of some iterator requirements. Iterators have to have a value_type (ignore the whole "iterator_traits" business for the moment; our intent is to use the default traits), which the derived class will provide. Our helper iterator CRTP base class will helpfully use the derived class value_type declaration to generate pointer, reference, and so forth. But the derived class's operator* needs to be able to return reference, which is inherited from the base class, which itself is dependent on compiling the value_type declaration in the derived class. So... which gets compiled first: the base class template instantiation or the derived class? It has to be one or the other; it can't be both at the same time.
The ultimate problem is that the CRTP is just not what we really want. What we really want is to be able to store a sequence of declarations/definitions in a centralized location, then inject them into a class as needed. IE: an actual mixin. Using inheritance of a template type that names the derived class is merely the closest tool the C++ language has to achieve that. But since inheritance and template instantiation were never intended to serve this need, there will naturally be warts associated with it.
So you will continue to have to rely on the typical alternative: using a "traits" class templated on the derived class type.
I am working with a GitHub library and ran across a derived class instantiation that perplexes me. In abbreviated form,
class A
{
public:
A() {}
int AFunc(void) { return(1); }
};
class B : public A
{
public:
B(void) : A() {}
int BFunc(void) { return(2); }
};
Within an include file, the class is instantiated as follows:
A &tObject = *(new B());
Sample code then refers to 'tObject' as global variable calling methods from class A and/or B.
For example:
tObject.AFunc();
tObject.BFunc();
So here's the question, is that instantiation legal?
The compiler is only fussing on the call to a service class's method, saying that class A has no such member. That error makes sense to me and I've narrowed the issue to the above explanation.
While I do not have broad compiler experience, I have been programming in C++ for many years. I've never seen such a construct.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
In my experience, I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct. Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
An insight is highly appreciated.
It cannot. The compiler is right to complain, there is no way this is valid. Remember that C++ is a static language, which means that the compiler will try to find a function named BFunc in A, which it cannot, as there is no such function.
This might be a compiler extension of some sort, but anyways, this isn't legal standard C++. Most probably, the author wanted to make BFunc a virtual method in A, which would have made the access legal.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
As explained, this cannot be.
I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct.
You can also do this with references, not just with pointers. Although this is done less often than pointers, so this might explain why you haven't encountered this yet.
Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
Exactly, this is the correct way to access the derived class members. As then the compiler will know the type of the object and can actually find BFunc and call it. Now, if the type is not really a B, then you have undefined behavior, but yes, this is what one should do.
Also, please get your terminology right:
the class is instantiated as follows
If there are no templates involved, then there is no instantiation happening. The only thing you are doing here is declaring or more specifically defining a variable named tObject.
// The declaration of the reference as a reference to the base class is not a problem, and is actually performed in some STL implementations.
class A
{
};
class B : public A
{
public:
void f1() {}
};
int main()
{
A * a = new B; // You know its OK using pointers
A & a2 = *(new B); // Also OK, a2 is a reference for a place in memory which is-a-kind-of A
// a2.f1(); // Will not compile - compiler only knows for sure its of type A
((B&) a2).f1(); // This will work. There is really a B there
return 0;
}
I have this particular case and would need some opinion on some of the design aspects.
Basically, I have already defined classes ( which represents position in different spaces ) and the classes does not have a concrete relationship to each other.
So, I designed a template based interpolator which can work on the currently available position representing classes.
Roughly like,
template<typename TPoint>
class Interpolator
{
.....
some function
{
TPoint::CalculateCriticalAxis(point);
}
}
As you can see, there are some static functions defined in all position classes that can be accessed inside the interpolator.
So, now since somebodyelse who need to use the interpolator and define a new position(point) class, will have to know that he needs to define them by looking at the code since there is no base class for positions.
The question is how can I design a base class which will also contain static methods which user have to override. As I understand static methods can not be overridden. So, what is the easiest way to force implementing them if somebody want to define a new position(point) class.
I do not want to redesign it since there are legacy position classes that are not from me and they non related in some sense.
Thanks!
Use a static member function, defined as deleted. A [[deprecated( "message" )]] attribute allows you to print an error message when someone tries to access a missing implementation.
// May be, but doesn't need to be a template.
struct base_interface {
// Likewise, this could be templated.
[[deprecated( "Derived class must override calculation." )]]
static value_type calculate_something() = delete;
// "Public" interface, in the vein of the non-virtual idiom (NVI).
// This must be a template, and it can't be a member - it's a friend.
template< typename derived >
friend value_type something_of( derived const & o )
{ return o.calculate_something(); }
};
The well-known weakness of "duck typing" is that the user might not try to access the missing implementation. This is a different problem. Any solution amounts to accessing all the aspects of a proper derived class.
A base class can do this, but only carefully, because there are some issues:
The derived class will be incomplete within the definition of its base class. But, it will be complete within the definitions of member functions of the base class.
The existence of a complete derived class implementation should be verified, but you don't actually want to instantiate all parts of a derived class template, much less link it into the binary. "Too much" usage will bloat compile times and executable size, respectively.
One solution is to use static_assert and decltype inside a CRTP base class constructor.
// CRTP template, derived class must pass itself to base.
template< class derived >
class base_interface {
base_interface() {
static_assert ( std::is_same< decltype( derived::calculate_something() ),
typename derived::value_type >::value,
"derived class is missing calculate_something" );
}
// Just enough to allow the static_assert condition to evaluate as false.
static struct invalid calculate_something();
typedef void value_type;
};
http://coliru.stacked-crooked.com/a/b2c5f9bf8ed58a09
Note that this is a completely different solution from the first one. This prevents the CRTP base from being trivially default constructible, but that's a fairly small price to pay. Alternately, you could put the static_asserts in a different function that is sure to be accessed, and retain the trivial default constructor.
I've been trying to understand a piece of code that goes like this:
class A {
// some class definition
}
class B {
public:
virtual A *someMethod();
virtual class A *someOtherMethod();
}
I can't seem to understand the difference (or if any exists, for that matter) between someMethod and someOtherMethod - both appear to be virtual methods and both are overridden in classes that inherit from B.
Could someone shed some light on this virtual class syntax?
A is the class name, and class A is the elaborated type specifier.
If there's nothing else called A, then both refer to the class called A.
If there were something else (a function or variable, perhaps) called A, then an unqualified use of A would refer to that. You'd need the elaborated specifier class A to refer to the class. As mentioned in the comments, you can also use class A without a previous declaration of the class; the use of the elaborated specifier is enough to introduce the class name into the innermost namespace.
It has little to do with virtual function syntax; both forms can be used to specify the type, whether as the return type of a function or in any other context.
In C you used to have to write struct S to refer to a structure. In fact there was this pattern to deal with it: typedef S struct {}, which creates an unnamed structure, then gives it the name S through type aliasing.
C++ retained this ability, but aliases raw types automatically. In your case, A is a type alias to the formal name class A. Of course the automatic alias won't work if you have more than one A, but that's also a pretty big code smell.
TL;DR: both functions return the same thing. It's a remnant of C for backwards compatibility and extremely frowned upon when used.
Unfortunately, I studied class design and design patterns mostly in the context of Java; thus, I sometimes have a hard time to translate a familiar pattern to C++.
Assume we want to have a base class which's functionality is extended by a sub-class. In Java, we would do something like this:
public class BaseClass<T> {
//T is used here
protected int foo = 0;
}
public class DerivedClass<T> extends BaseClass<T> {
public void incr_foo() {
++foo;
}
}
Which I directly translated to C++:
template<class T>
class BaseClass {
protected:
size_t foo = 0;
//T is used here
};
template<class T>
class DerivedClass : public BaseClass<T> {
public:
void incr_foo() {
++(this->foo);
}
};
Since the C++ semantics of 'protected' diver from the Java-semantics, we need to use something like 'this->foo' to access protected members of the base class.
Edit: If we just use '++foo', the compiler gives the error: 'use of undeclared identifier foo'.
EditEnd
If you need to access several members of the base class, this can get a bit tedious and is not so nice to read.
Is this a good design desicion? If not, what better ways are there to achieve this?
This has nothing to do with the member being protected; you'd get the exact same error with a public member.
The real reason is that templates are involed. More specifically, that your class template has a base class which depends on a template parameter. This means that when parsing the template, the compiler will not (be able to) look into that base class to find inherited members which are used unqualified. It makes sense: when the template is parsed, the template parameter values are not known yet and thus the compiler has no idea what members the base class will have (remember partial and total specialisation exist!).
In order to overcome this, you must somehow tell the compiler that the name foo depends on template parameters (that it's a dependent name). Once you do so, the compiler will not try to resolve it when parsing the template; it will postpone resolution until the template is instantiated. At that point, template arguments are known and thus the base class can be checked.
You have three ways to mark a member name as dependent:
Refer to the name through this, as you're doing: this->foo
Refer to the name through base-class qualification: BaseClass<T>::foo
Bring the name into the scope of the derived class:
template<class T>
class DerivedClass : public BaseClass<T> {
protected:
using BaseClass<T>::foo; // from this point on, `foo` is a dependent name
public:
void incr_foo() {
++foo; // works fine now
}
};
BaseClass<T> is a dependent type - it depends on the template parameter used to instantiate DerivedClass. Until DerivedClass instantiated, the compiler doesn't know what the type is: it might be an instantiation of the generic template, or it might be an explicit specialisation, with different members.
So, within the definition of DerivedClass, there is no way to know which names refer to members of the base class. You have to specify that they are, using this-> or BaseClass::.
In a class with a non-dependent base class, you can use any accessible base-class members as if they were direct members, just as in Java.