Extending class methods in C++ with templates - c++

In contrast with other languages, C++ classes cannot be extended once defined.
This is why free functions are preferable to member functions because these are more general way to extend the behavior of a class.
At the same time, the dot syntax (only used for member functions) can have some notational advantage, for example when there is an object that is "more important" than the rest of the arguments in a function call.
For example,
allocator a;
a.allocate(n); // vs. allocate(a, n);
This creates a tension in the language.
(A tension that in early C++ contributed to the creation of bloated classes.)
In the best case, the difference is syntactic.
In the worst case the desired syntax using dot forces the methods to be defined inside the class (with the risk of making the class to large by including a lot of member functions).
This is what C++ is so far, and we are used to live with this.
However there is, for some cases a loop hole.
The question is whether this loop hole is frequently exploited or if it can create problems down the road.
The fact is that one can emulate extensions of a class by leaving template member function open.
For example:
struct A{
void f(int n) const{...}
void g(std::string s) const{...};
};
The "member" g cannot be extended to make this work A a; a.g(42).
However one can do this to make the syntax work:
struct A{
void f(int n) const{}
template<class T> void g(T t) const; // this can be even customized by a user of the library
};
// this can be defined anywhere down the road (but before `A::g<T>` is instantiated I think).
template<> void A::g<int>(int t) const{}
template<> void A::g<std::string>(std::string t) const{}
The extension is not general, any extension will have to have a fixed name (and one parameter) in this case but it feels like an extension nevertheless.
Besides the ugly out of class template code, is there any problem in using this technique to extend classes?
It is not straightforward in the general case but the technique can be even extended to customize different return types I think (here I used void for simplicity, another simple cases is when the return type is T itself also).
A problem I can see is that partial specialization is probably very difficult.
Another one is that order of instantiation can be problematic, the customizations need to be defined before first use (?).
Customizing a named function is not very impressive.
But other functions like template<class T> operator=(T const); can be customized. Effectively, this is like overloading assignment from outside the class which is not possible by normal means.

Besides the ugly out of class template code, is there any problem in using this technique to extend classes?
No, it is called "member templates" and it is a perfectly valid thing in C++.
Update:
I know it is valid. I am wondering if this is a technique frequently used.
I've personally never used it that often. Usually, have been deciding to implement the whole class as a template rather than focusing on individual functions. Yet at the same time I believe this sort of things depend on what you are trying to achieve and what is your personal taste. I mean it is a feature of the language and so why not use it whenever it feels like it would suit.

Related

reducing countless template keywords in C++?

I have a pretty simple code as the following.
template<typename T>
struct cell{
int nr;
T* someInfo;
};
template<typename T>
void doSomething(cell<T> c)
{
cout<<c.nr;
}
I actually have numerous functions using cells, very few using the T* template info (above code does not use it). Can I write my program (in C++98) without ending up with
countless template keywords, T* or cell stuff? I want to reduce clutter, to write a
rather C-like C++ code, easy to read by those who are not familiar with
C++. Can I make the compiler understand (without macros) that whenever it sees cell, it
is actually cell<T> and it has to put a template on the function?
If there is no C++98 solution, I prefer a C way using void* instead of T*. That comes with no clutter in the rest of the code, but I can't delete c.someInfo, but only
free(c.someInfo).
Reuse code by inheritance from a non-templated base class.
struct cell_base {
int nr;
};
template<typename T>
struct cell : cell_base {
T* someInfo;
};
void doSomething(cell_base const& c)
{
cout<<c.nr;
}
So whatever needs the non-templated bits accepts a cell_base, and the few things that do need the template parameter can be templates.
If you want to use templates, then you need to use the correct template syntax.
Which does indeed mean writing T quite a few times as well as template<typename T>. That's life: the compiler does some very clever things, and needs this "boilerplate" in order to disambiguate.
You can reduce the amount of typing by writing all the functions inline inside the class declaration.
Using (void*) instead would be anachronistic.
You can typedef your template; and which will completely hide the fact that it's a template for a specific type. ie
typedef cell<int> IntCell;
then usage of the type
void doSomething(const IntCell& c) {}
Edit: I now realize that you asked about c++98. My suggestion requires c++14 unfortunately.
You could use generic lambdas in place of template functions:
auto doSomething = [](auto c) {
cout<<c.nr;
}
If you're willing to wait for a bit, there is the concepts proposal for the C++ standard which will hopefully be included in C++20. It includes generic functions which could allow:
void doSomething(auto c)
{
cout<<c.nr;
}
Or
void doSomething(Concept c)
{
cout<<c.nr;
}
Where Concept is a concept that all cell<T> satisfy. This is a compile time analogue to the runtime inheritance suggested by StoryTeller.
Hoping this can be useful for somebody someday, I'll explain why I ended up with the
old-school C solution in C++. You maybe need to be in the same mess as me to understand,
i.e., you need to deal with some minor unknown pointer for which you do not want to clutter
a C++ code which already has many classes that can not be ported to C in reasonable time.
I thank all the responses I received, and after considering them, I regret they could not solve
my problems. Even with inheritance, I still end up with hundreds of template and <T>
stuff because I have many classes and sub-classes with cell members.
It is easier/cleaner to use void* someInfo as in C, as that does not require modifying all
classes that contain cells. The problem of deleting the void* pointer is left to the user
of the library. It's easy to allow/ask the user to make a unique call like
set_func_free_info(&custom_free_func). The deallocation function of the library could be:
if(func_free_info!=NULL)
func_free_info(c.someInfo);
else //don't let it get here if someInfo points to an object
free(c.someInfo); //needing a destructor, do use set_func_free_info(...).
Given some of the responses, I feel you :
might argue void* is "anachronistic". Maybe. If somebody told me that such an old language
like English is anachronistic faced to modern Esperanto, I would feel the same.
might say it is a bad idea to write code somehow for pure C programmers not familiar
with C++, in the line with a above remark ``the code ends up more complex than it needs to be
so even those who ARE familiar with C++ end up getting confused.''. If you honestly
think about this, here the opposite is true : the code is less complex by avoiding C++
features, as the template constructs would clutter all the code for a minor feature.
ask why don't stick to pure C and simply finish the story. I can't, because this is
part of a code where someInfo can be an object. So I end up
with the C-like C++ style that some here seem to hate, but you can really find reasons for it on
the linked material my comment above.
Anyway, M Stroustrup said that
C++ is deliberately designed to support a variety of
styles rather than a would-be "one true way".
So if you like to lecture about "your
true C++ way", you should understand you shouldn't do it. And you'll see life so much
more than a foolish game. C++ supports infinitely many more styles and possibilities than
C, e.g., I could use lambdas as in one of the replies, but too many would not understand it.

Static polymorphism: How to define the interface?

Below is a very simple example of what I understand as static polymorphism. The reason why I'm not using dynamic polymorphism is that I do not want to obstruct inlining of functions of PROCESSOR in op.
template <class PROCESSOR>
void op(PROCESSOR* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
int main() {
ProcessorY py;
op<ProcessorY>(&py);
return 0;
}
The problem with this example is: There exists no explicit definition of what functions a PROCESSOR has to define. If one is missing, you will just get a compile error. I think this is bad style.
It also has a very practical drawback: On-line assistance of IDEs cannot of course show you the functions that are available on that object.
What is a good/official way to define the public interface of a PROCESSOR?
There exists no explicit definition of what methods a PROCESSOR has to define. If one is missing, you will just get a compile error. I think, this is bad style.
It is. It is not. It may be. It depends.
Yes, if you want to define behavior in this way, you may want to also restrict the content, that template parameters should have. Unfortunately, it is not possible to do this "explicitly" right now.
What you want is constraints and concepts feature, that was supposed to appear as part of C++ 11, but was delayed and is still not available as of C++ 14.
However, getting compile-time error is often the best way to restrict template parameters. As an example, we can use std library:
1) Iterators.
C++ library defines few types of iterators: forward_iterator, random_access_iterator and others. For each type, there is a set of properties and valid expressions defined, that are guaranteed to be available. If you used iterator, that is not fully compatible with random_access_iterator in container, that requires random_access_iterator, you will get compiler error at some point (most likely, when using dereference operator ([]), which is required in this iterator class).
2) Allocators.
All containers in std library use allocator to perform memory allocation/deallocation and objects construction. By default, std::allocator is used. If you want to exchange it with your own, you need to ensure, that it has everything, that std::allocator is guaranteed to have. Otherwise, you will get compile-time error.
So, until we get concepts, this is the best and most widely used solution.
First, I think there is no problem with your static polymorphism example. Since it's static, i.e. compile-time resolved, by definition it has less strict demands regarding its interface definition.
Also it's absolutely legitimate that the incorrect code just won't compile/link, though a more clear error message from the compiler would be nicer.
If you, however, insist on interface definition, you may rewrite your example the following way:
template <class Type>
class Processor
{
public:
void doSomething(int);
void doSomethingElse();
};
template <class Type>
void op(Processor<Type>* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
// specialization
template <>
class Processor<Type_Y>
{
// implement the specialized methods
};
typedef Processor<Type_Y> ProcessorY;
int main() {
ProcessorY py;
op(&py);
return 0;
}

C++ concepts vs static_assert

What is exactly new in c++ concepts? In my understanding they are functionally equal to using static_assert, but in a 'nice' manner meaning that compiler errors will be more readable (as Bjarne Stroustup said you won't get 10 pages or erros, but just one).
Basically, is it true that everything you can do with concepts you can also achieve using static_assert?
Is there something I am missing?
tl;dr
Compared to static_asserts, concepts are more powerful because:
they give you good diagnostic that you wouldn't easily achieve with static_asserts
they let you easily overload template functions without std::enable_if (that is impossible only with static_asserts)
they let you define static interfaces and reuse them without losing diagnostic (there would be the need for multiple static_asserts in each function)
they let you express your intents better and improve readability (which is a big issue with templates)
This can ease the worlds of:
templates
static polymorphism
overloading
and be the building block for interesting paradigms.
What are concepts?
Concepts express "classes" (not in the C++ term, but rather as a "group") of types that satisfy certain requirements. As an example you can see that the Swappable concept express the set of types that:
allows calls to std::swap
And you can easily see that, for example, std::string, std::vector, std::deque, int etc... satisfy this requirement and can therefore be used interchangeably in a function like:
template<typename Swappable>
void func(const Swappable& a, const Swappable& b) {
std::swap(a, b);
}
Concepts always existed in C++, the actual feature that will be added in the (possibly near) future will just allow you to express and enforce them in the language.
Better diagnostic
As far as better diagnostic goes, we will just have to trust the committee for now. But the output they "guarantee":
error: no matching function for call to 'sort(list<int>&)'
sort(l);
^
note: template constraints not satisfied because
note: `T' is not a/an `Sortable' type [with T = list<int>] since
note: `declval<T>()[n]' is not valid syntax
is very promising.
It's true that you can achieve a similar output using static_asserts but that would require different static_asserts per function and that could get tedious very fast.
As an example, imagine you have to enforce the amount of requirements given by the Container concept in 2 functions taking a template parameter; you would need to replicate them in both functions:
template<typename C>
void func_a(...) {
static_assert(...);
static_assert(...);
// ...
}
template<typename C>
void func_b(...) {
static_assert(...);
static_assert(...);
// ...
}
Otherwise you would loose the ability to distinguish which requirement was not satisfied.
With concepts instead, you can just define the concept and enforce it by simply writing:
template<Container C>
void func_a(...);
template<Container C>
void func_b(...);
Concepts overloading
Another great feature that is introduced is the ability to overload template functions on template constraints. Yes, this is also possible with std::enable_if, but we all know how ugly that can become.
As an example you could have a function that works on Containers and overload it with a version that happens to work better with SequenceContainers:
template<Container C>
int func(C& c);
template<SequenceContainer C>
int func(C& c);
The alternative, without concepts, would be this:
template<typename T>
std::enable_if<
Container<T>::value,
int
> func(T& c);
template<typename T>
std::enable_if<
SequenceContainer<T>::value,
int
> func(T& c);
Definitely uglier and possibly more error prone.
Cleaner syntax
As you have seen in the examples above the syntax is definitely cleaner and more intuitive with concepts. This can reduce the amount of code required to express constraints and can improve readability.
As seen before you can actually get to an acceptable level with something like:
static_assert(Concept<T>::value);
but at that point you would loose the great diagnostic of different static_assert. With concepts you don't need this tradeoff.
Static polymorphism
And finally concepts have interesting similarities to other functional paradigms like type classes in Haskell. For example they can be used to define static interfaces.
For example, let's consider the classical approach for an (infamous) game object interface:
struct Object {
// …
virtual update() = 0;
virtual draw() = 0;
virtual ~Object();
};
Then, assuming you have a polymorphic std::vector of derived objects you can do:
for (auto& o : objects) {
o.update();
o.draw();
}
Great, but unless you want to use multiple inheritance or entity-component-based systems, you are pretty much stuck with only one possible interface per class.
But if you actually want static polymorphism (polymorphism that is not that dynamic after all) you could define an Object concept that requires update and draw member functions (and possibly others).
At that point you can just create a free function:
template<Object O>
void process(O& o) {
o.update();
o.draw();
}
And after that you could define another interface for your game objects with other requirements. The beauty of this approach is that you can develop as many interfaces as you want without
modifying your classes
require a base class
And they are all checked and enforced at compile time.
This is just a stupid example (and a very simplistic one), but concepts really open up a whole new world for templates in C++.
If you want more informations you can read this nice article on C++ concepts vs Haskell type classes.

Designing hiearchical classes with template function

I am writing a class Base which has a member function taking a template parameter:
class Base {
template<class T>
void func(const T& t) { ... }
};
There's a class Derived which conceptually inherits natures of Base and has the same function func with different implementation.
At first I thought of deriving Derived from Base and make func virtual, but I can't because it's template.
I also thought of CRTP, but it's an option because instances must be able to put into a container and be accessible without knowing exact types of them:
std::vector<Base*> v = ...;
v[0]->func(...);
v[1]->func(...);
Overloading for possible types of T is also not an option.
What is the best solution to this situation?
And aside from the topic, would you recommend references (preferably books) for such kind of problems?
You cannot mix compile time polymorphism (templates) with runtime polymorphism like that. The problem is that with a template, the compiler will generate the code on-demand when it is used, and in your particular case, you want to decide what member function to instantiate based on the runtime type of the object in the vector.
If the number of types that can be used with the methods is limited, you can provide different virtual overloads, if you don't want to do that manually, you can probably define a type list with all of the types T, and then use that typelist to generate the methods... but that will be awful to code and maintain.
I recommend that you state the actual requirements of the problem (rather than the requirements of your proposed solution), and people will be able to provide alternative approaches.
This is not something easily done with C++. It's related to something called "first class polymorphism", which means it would be easy if the values in C++ could have polymorphic types. This is not the case.
If you'll be fine with a generic solution (that means the code f must be the same for all T), you can maybe do it, but it will be a laborious task.
Basically, you'll want to replace your const T &t parameter with a parameter whose type that wouldn't be generic, but will capture "inside" all the behaviour f needs from ts of all possible types.
For an example, let's say T is meant to be a functor, that f calls with an int argument. In this case, you'll change the declaration to
virtual void func(const std::function<void(int)>& t) { ... }
and virtual functions will start to work. However, that means the interface of Ts will have to be fixed before you start to implement it in derived classes (meaning if you change your mind and want to call t with an argument of type ostream, you're out of luck).
However, creating such polymorphic wrappers ranges from easy (as is boost::any, boost::function) to hard or even impossible (any_iterator). It's very dependent on what you want to do.

Enforce functions to implement for template argument class?

Should I define an interface which explicitly informs the user what all he/she should implement in order to use the class as template argument or let the compiler warn him when the functionality is not implemented ?
template <Class C1, Class C2>
SomeClass
{
...
}
Class C1 has to implement certain methods and operators, compiler won't warn until they are used. Should I rely on compiler to warn or make sure that I do:
Class C1 : public SomeInterfaceEnforcedFunctions
{
// Class C1 has to implement them either way
// but this is explicit? am I right or being
// redundant ?
}
Ideally, you should use a concept to specify the requirements on the type used as a template argument. Unfortunately, neither the current nor the upcoming standard includes concepts.
Absent that, there are various methods available for enforcing such requirements. You might want to read Eric Neibler's article about how to enforce requirements on template arguments.
I'd agree with Eric's assertion that leaving it all to the compiler is generally unacceptable. It's much of the source of the horrible error messages most of us associate with templates, where seemingly trivial typos can result in pages of unreadable dreck.
If you are going to force an interface, then why use a template at all? You can simply do -
class SomeInterface //make this an interface by having pure virtual functions
{
public:
RType SomeFunction(Param1 p1, Param2 p2) = 0;
/*You don't have to know how this method is implemented,
but now you can guarantee that whoever wants to create a type
that is SomeInterface will have to implement SomeFunction in
their derived class.
*/
};
followed by
template <class C2>
class SomeClass
{
//use SomeInterface here directly.
};
Update -
A fundamental problem with this approach is that it only works for types that is rolled out by a user. If there is a standard library type that conforms to your interface specification, or a third party code or another library (like boost) that has classes that conform to SomeInterface, they won't work unless you wrap them in your own class, implement the interface and forward the calls appropriately. I'm somehow not liking my answer anymore.
Absent of concepts, a for now abandoned concept (pun not intended, but noted) for describing which requirements a template parameter must fulfill, the requirements are only enforced implicitly. That is, if whatever your users use as a template parameter doesn't fulfill them, the code won't compile. Unfortunately, the error message resulting from that are often quite gibberish. The only things you can do to improve matters is to
describe the requirements in your template's documentation
insert code that checks for those requirements early on in your template, before it delves so deep that the error messages your users get become unintelligibly.
The latter can be quite complicated (static_assert to the rescue!) or even impossible, which is the reason concepts where considered to become a core-language feature, instead of a library.
Note that it is easy to overlook a requirement this way, which will only become apparent when someone uses a type as a template parameter that won't work. However, it is at least as easy to overlook that requirements are often quite lose and put more into the description than what the code actually calls for.
For example, + is defined not only for numbers, but also for std::string and for any number of user-defined types. Conesequently, a template add<T> might not only be used with numbers, but also with strings and an infinite number of user-defined types. Whether this is an unwanted side-effect of the code you want to suppress or a feature you want to support is up to you. All I'm saying is that it is not easy to catch this.
I don't think defining an interface in the form of an abstract base class with virtual functions is a good idea. This is run-time polymorphism, a main pillar classic OO. If you do this, then you don't need a template, just take the base class per reference.
But then you also lose one of the main advantages of templates, which is that they are, in some ways, more flexible (try to write an add() function classic OO which works with any type overloading + in) and faster, because the binding of the function calls take place not at run-time, but during compilation. (That brings more than it might look like at first due to the ability to inline, which usually isn't possible with run-time polymorphism.)