Equivalent to `<T extends MyClass>` in C++ - c++

In Java you can define a generic type, that should interhit from anoter, by <T extends MyClass> void myMethod(T item)
Is there an equivalent in cpp? I tried template<class T : Draw_Shape> class MyClass, but dont work.

When reading below, please be aware that I am not a Java programmer. My knowledge of Java is almost entirely abstract, and possibly out of date. So if Java implemented reification of generics in the last version or two I don't know about it.
So Java Generics and C++ templates share some common syntax and uses, but they are very different things under the hood.
Java Generics are a wrapper of automatically written casts and compile time type checks around a single core type.
C++ templates on the other hand generate new unrelated types for each set of template arguments.
The extends MyClass syntax in Java does two things. First, it permits that "core" type of the generic to know that the T is not merely an Object, but actually a subclass of some interface. This is required for the "core" type to use methods safely (without can-fail-at-runtime dynamic casts).
In C++ this doesn't happen because there is no "core" type generated by a template instantiation. Each template instantiation is independently compiled, and so knows if the operations are valid or not.
The second thing it does is it gives type errors when the wrong type is passed to the generic. The third thing it does is it allows Java to check the Generic code for validity prior to it being instantiated.
For the second, C++ can use concepts (if your compiler is new enough) or use a technique known as SFINAE that is equally powerful, but syntactically awful and honestly its ability to solve this problem was an accident of language development (it is accidentally Turing complete).
For the third, checked templates in C++, it has been proposed many times, but keeps running into compile time performance issues. So there isn't a way to do it in C++, short of instantiating a template.
Solutions:
Do nothing:
No, seriously. Embrace duck typing and don't constrain template parameters. The only big downside is ugly error messages, and rarely "same named operation has different meanings".
static_assert:
template<class T> class MyClass{
static_assert(std::is_base_of_v<Draw_Shape,T>);
};
this generates clean error messages. There are some downsides in that other code cannot test if MyClass<X> is a valid instantiation without a hard compiler error.
SFINAE:
template<class T,
std::enable_if_t<std::is_base_of_v<Draw_Shape,T>, bool> =true
>
class MyClass{
};
note that the =true does not compare the test to the value true. It is not ==true. What is going on here is ridiculously complex and annoying; using SFINAE for this purpose is a hack, and this is just a monkey-see monkey-do way to make it clean.
Concepts:
template<class T> requires std::is_base_of_v<Draw_Shape,T>
class MyClass{
};
or
template<std::is_derived_from<Draw_Shape> T>
class MyClass{
};
note that concepts requires a modern C++ complier and std library.

Related

Is CRTP in C++ a way to express what in other languages are traits and/or ADT?

So, I'm struggling to grasp the whole CRTP thing in C++. A few (1) (2) of the rationales I found online about why should you even care to use it is that it allows to add a functionality to your code in a semi automatic way. What I mean is that I can let the compiler deduce some functionality for me, asking me only for a few small implementation.
As an example, I may want to formalize a Comparable "trait" (using a Rust word), forcing the user to provide an implementation for < and ==, and deducing all other comparisons using just these two. IIRC, this is what happens when you instantiate a std::set of a custom class (the compiler asks you for a operator<() implementation).
So, I have two question about C++'s CRTP:
In this sense, is the usage of the word "trait" appropriate? And may I even go further and say abstract data type? Is CRTP the C++ idiom to achieve this (C++ purists, forgive me)? Because to me they seem very similar: you define some basic implementation, and following some deduction rules you can get other behavior/functionality
Can I get the same thing ("trait"-like thing) by using an abstract class? If so, why should I use a CRTP instead?
Thanks!
EDIT: in the comments I have been advised that in C++ the word "trait" refers to a particular concept, which is different to the one used for instance in Rust. So I slightly change/clarify my question: is CRTP similar to Rust's traits (IIUC, specifically the #[derive]d ones)?
The CRTP idiom is a tool that injects generic functionality into a class, specifically by inserting members into it. The general, language-neutral, term for this kind of thing is a "mixin." Mechanically, "mixin" usually refers to ways of injecting members into a class without using a base class. Since the CRTP uses base classes, it does not strictly fit the definition of a mixin. But this is a matter of mechanism, not concept; a CRTP base class fulfills the general function of a mixin even if not by the usual means.
Rust traits are kind of like mixins as well. But the CRTP is not like a Rust trait for one very important reason. The whole point of Rust traits is that the class on the receiving end does not have to know that they are being given a trait. In Rust, you can force a type to have a trait interface without that type having any idea that the trait even exists.
The CRTP can't do that. A class must choose to opt-into a CRTP-based mixin interface.
So no, I would not call the CRTP a Rust trait. Indeed, the C++ concept you found called "traits" are much more like Rust traits. C++ traits define an interface that any type could adopt, and via template specialization, a user can adapt its normal interface to the traits interface. Same idea, just via a different mechanism.
The nominal similarity is not a coincidence: the makers of Rust recognized the utility of the C++ traits idiom and built a language feature specifically to facilitate it (and thus dodging all of the cruft that comes from using traits-based interfaces in C++).
In addition to #Nicol Bolas excellent answer I would like to add some comments on #[derive] traits. In rust, you can automatically implement some traits for your structs using this keyword. Here is an example taken from the link above:
#[derive(PartialEq)]
struct Foo<T> {
a: i32,
b: T,
}
The equivalent in C++ would be an automatic mixin of code, such that Foo fufills the std::equality_comparable concept. This is currently impossible because an automatic implementation would require a built-in reflection system, which C++ does not have: We would have to inject an equality operator, that checks all data members for equality, so we need to know about all data members of the type we are injecting the functionality into. There is a current proposal for built-in reflection, but even with it, it would probably be impossible to write a CRTP base class PartialEq that implements a meaningful bool operator==(X const& other) const noexcept for you. Consider the following example:
// hypothetical crtp mixin
template <typename T>
struct Foo : public PartialEq<Foo<T>> {
int a;
T b;
};
PartialEq<Foo<T>> needs to know about all datamembers of Foo<T>, but at time of the definition of PartialEq, Foo<T> is incomplete: It must be defined afterwards, because it depends on PartialEq through inheritence.
But there is yet another proposal on facilitating metaprogramming in C++ that introduces features somewhat similar to procedural macros in rust. If it gets accepted and implemented, it will be added no earlier than 2026. This proposal includes something called a metaclass, which pretty much is very close to a #[derive] trait in rust - without CRTP. The syntax would look like this:
template <typename T>
struct Foo(PartialEq) {
int a;
T b;
};
This usage scenario is even explicitly mentioned in the proposal paper, though there is a talk of a regular interface (a supertrait, in rust-speak), that injects code to satisfy the equality_comparable concept together with some other code.

How to know the required interface/contract of template arguments in C++?

Sorry for the newbie question, but I have a feeling I am missing something here:
If I have a certain class template which looks like this (basically the only way to pass a lambda to a function in C++, unless I am mistaken):
template<typename V, typename F>
class Something
{
public:
int some_method(V val, F func) {
double intermediate = val.do_something();
return func(intermediate);
}
}
By reading the implementation of this class, I can see that the V class must implement double do_something(), and that F must be a function/functor with the signature int F(double).
However, in languages like Java or C#, the constraints for the generic parameters are explicitly stated in the generic class signature, so they are obvious without having to look at the source code, e.g.
class Something<V> where V : IDoesSomething // interface with the DoSomething() method
{
// func delegate signature is explicit
public int SomeMethod(V val, Func<double, int> func)
{
double intermediate = val.DoSomething();
return func(intermediate);
}
}
My question is: how do I know how to implement more complex input arguments in practice? Can this somehow be documented using code only, when writing a library with template classes in C++, or is the only way to parse the code manually and look for parameter usage?
(or third possibility, add methods to the class until the compiler stops failing)
C# and Java Generics have similar syntax and some common uses with C++ templates, but they are very different beasts.
Here is a good overview.
In C++, by default template checking was done by instantiation of code, and requrements are in documentation.
Note that much of the requirements of C++ templates is semantic not syntactic; iterators need not only have the proper operations, those operations need to have the proper meaning.
You can check syntactic properties of types in C++ templates. Off the top of my head, there are 6 basic ways.
You can have a traits class requirement, like std::iterator_traits.
You can do SFINAE, an accidentally Turing-complete template metaprogramming technique.
You can use concepts and/or requires clauses if your compiler is modern enough.
You can generate static_asserts to check properties
You can use traits ADL functions, like begin.
You can just duck type, and use it as if it had the properties you want. If it quacks like a duck, it is a duck.
All of these have pluses and minuses.
The downside to all of them is that they can be harder to set up than "this parameter must inherit from the type Foo". Concepts can handle that, only a bit more verbose than Java.
Java style type erasure can be dominated using C++ templates. std::function is an example of a duck typed type eraser that allows unrelated types to be stored as values; doing something as restricted as Java is rarely worthwhile, as the machinery to do it is harder than making something more powerful.
C# reification cannot be fully duplicated by C++, because C#'s runtime environment ships with a compiler, and can effectively compile a new type when you instantiate at runtime. I have seen people ship compilers with C++ programs, compile dynamic libraries, then load and execute them, but that isn't something I'd advise.
Using modern c++20, you can:
template<Number N>
struct Polynomial;
where Number is a concept which checks N (a type) against its properties. This is a bit like the Java signature stuff on steroids.
And by c++23 you'll be able to use compile time reflection to do things that make templates look like preprocessor macros.

Bounded Type Parameters in C++, any reason for the lack of it?

Java and I guess C#(and others) support Bounded Type Parameters which lets us restrict what types may be used in template classes/functions.
I am curious if there is a reason, official or otherwise, for not adding native support for bounded types to C++? Anything to do with how templates are currently processed? Multiple inheritance issues?
I would expect it to be quite useful.
C++ has SFINAE which can be exploited via std::enable_if fairly easily. In conjunction with type_traits it is actually, IMO, more powerful than the bounded types that Java and C# have. With a little work you can also make some nice constexpr functions to test these things out for you. Combine that with some macros and you have something that looks sorta like it
#include <iostream>
#include <type_traits>
#define ENABLE_IF typename std::enable_if<
#define THEN(T) ,T>::type
class foo {};
class bar : public foo {};
template<class T, class U>
constexpr bool extends() {
return std::is_base_of<
typename std::remove_reference<U>::type,
typename std::remove_reference<T>::type
>::value;
}
template<class T>
ENABLE_IF extends<T, foo>() THEN(void) test(T&& v) {
std::cout << "T extends foo!!";
}
int main() {
test(bar{});
}
Now I'm not sure I would recommenced this but it is doable and as of now I see no issue in doing it beyond SFINAE being hard to debug
The simple fact is, the reason why this is not in is because nobody has come up with a feature that would make it work without horrific side effects. The Committee has been working on the problem for a decade or more, and the latest iteration still isn't fit for purpose.
Also, the generic restrictions you refer to are not bounded types at all. The only bound they support is "X inherits from Y", essentially, and frankly, SFINAE with std::is_base_of covers this situation just fine. C++ would need something far more powerful to be useful, since run-time inheritance is one of the least useful features.
Most of the time, the constraints on a template argument should not be on the type, but on the operations that the template needs. C++ does that, in a somewhat awkward way, simply because you get an error message if an operation that the template uses isn't there. For example:
template <class T>
void show(T t) {
std::cout << t << std::endl;
}
If you call this template function with a type that doesn't implement operator<< you'll get an error. The Java approach would be to define an interface with a print method, and require that the user pass an object of a type that implements that interface. The C++ approach doesn't require all that mechanism.
The problem with doing this in C++ is that you can get error messages that are very confusing. Often the missing operation is used in some low-level part of another template, and the error message has no clear relation to the code that you wrote. That's one of the drives behind concepts: the author of the template can set out what operations it uses, and passing an object whose type doesn't support those operations will result in a violation of the concept right at the interface, instead of deep within the implementation, so you will probably get a more useful error message.
The purpose of the bounded type parameter is to raise a compile-time error in case of a mismatch of the supplied type and a desired base-class, so this is easily achievable in C++11 and up, with a static_assert and supplying to it the value of the std::is_base_of as follows:
template <typename T>
class C {
static_assert(std::is_base_of<SomeBoundedBaseClass, T>::value, "Bounded type parameter violation!");
//...the rest of the class C
};
where SomeBoundedBaseClass is your class to which you want to bound the type parameter T to be a descendant of or match exactly.
Also note that this way you can mention any custom message to be shown as a compile error, so it has even an advantage over the Java's built-in functionality. Needless to say that C++ is more verbose, but it gives also more freedom.

Synthesizing the interface of T required by a class template

template <typename T>
class A
{
// use the type parameter T in various ways here
}
Is there any way to automatically synthesize a workable class definition for T, as used by the template A? My expectation is a tool or a compiler trick that could generate the boiler plate code for the type parameter T, which I could tweak further to my needs.
I know if I wrote the class A, I could provide some hints to the "user" using boost concepts checks etc... But it's an unfamiliar code base where I didn't have the luxury of writing class A. So far I build the needed parameter class T manually, by reading the code for class A and with the able assistance from the compiler (with its terse messages).
Is there a better way?
If I understand you correctly, you are looking for a way to automatically generate a concept archetype for a given template class. Currently, this is not possible and maybe it never will be.
The main problem here is that it is very hard to say anything about the semantics of As code without any a priori knowledge of T. Dave Abrahams wrote a blog post not too long ago, where he showed that it is possible to to call an unconstrained function from code that is constrained by concepts and the compiler will still be able to perform the concept checks correctly.
But what you are asking for is a compiler that synthesizes concept checks out of thin air. I'm not much of a compiler person but I can't think of a way to make this possible with today's tools. Although it surely would be very cool if this became possible some day.

typedef vs public inheritance in c++ meta-programming

Disclaimer: the question is completely different from Inheritance instead of typedef and I could not find any similar question so far
I like to play with c++ template meta-programming (at home mostly, I sometimes introduce it lightly at work but I don't want to the program to become only readable to anyone who did not bother learning about it), however I have been quite put out by the compiler errors whenever something goes wrong.
The problem is that of course c++ template meta-programming is based on template, and therefore anytime you get a compiler error within a deeply nested template structure, you've got to dig your way in a 10-lines error message. I have even taken the habit of copy/pasting the message in a text-editor and then indent the message to get some structure until I get an idea of what is actually happening, which adds some work to tracking the error itself.
As far as I know, the problem is mostly due to the compiler and how it output typedefs (there are other problems like the depth of nesting, but then it's not really the compiler fault). Cool features like variadic templates or type deduction (auto) are announced for the upcoming C++0x but I would really like to have better error messages to boot. It can prove painful to use template meta-programming, and I do wonder what this will become when more people actually get into them.
I have replaced some of the typedefs in my code, and use inheritance instead.
typedef partition<AnyType> MyArg;
struct MyArg2: partition<AnyType> {};
That's not much more characters to type, and this is not less readable in my opinion. In fact it might even be more readable, since it guarantees that the new type declared appears close to the left margin, instead of being at an undetermined offset to the right.
This however involves another problem. In order to make sure that I didn't do anything stupid, I often wrote my templates functions / classes like so:
template <class T> T& get(partition<T>&);
This way I was sure that it can only be invoked for a suitable object.
Especially when overloading operators such as operator+ you need some way to narrow down the scope of your operators, or run the risk of it been invoked for int's for example.
However, if this works with a typedef'ed type, since it is only an alias. It sure does not work with inheritance...
For functions, one can simply use the CRTP
template <class Derived, class T> partition;
template <class Derived, class T> T& get(partition<Derived,T>&);
This allows to know the 'real' type that was used to invoke the method before the compiler used the public inheritance. One should note that this decrease the chances this particular function has to be invoked since the compiler has to perform a transformation, but I never noticed any problem so far.
Another solution to this problem is adding a 'tag' property to my types, to distinguish them from one another, and then count on SFINAE.
struct partition_tag {};
template <class T> struct partition { typedef partition_tag tag; ... };
template <class T>
typename boost::enable_if<
boost::same_type<
typename T::tag,
partition_tag
>,
T&
>::type
get(T&)
{
...
}
It requires some more typing though, especially if one declares and defines the function / method at different places (and if I don't bother my interface is pretty soon jumbled). However when it comes to classes, since no transformation of types is performed, it does get more complicated:
template <class T>
class MyClass { /* stuff */ };
// Use of boost::enable_if
template <class T, class Enable = void>
class MyClass { /* empty */ };
template <class T>
class MyClass <
T,
boost::enable_if<
boost::same_type<
typename T::tag,
partition_tag
>
>
>
{
/* useful stuff here */
};
// OR use of the static assert
template <class T>
class MyClass
{
BOOST_STATIC_ASSERT((/*this comparison of tags...*/));
};
I tend to use more the 'static assert' that the 'enable_if', I think it is much more readable when I come back after some time.
Well, basically I have not made my mind yet and I am still experimenting between the different technics exposed here.
Do you use typedefs or inheritance ?
How do you restrict the scope of your methods / functions or otherwise control the type of the arguments provided to them (and for classes) ?
And of course, I'd like more that personal preferences if possible. If there is a sound reason to use a particular technic, I'd rather know about it!
EDIT:
I was browsing stackoverflow and just found this perl from Boost.MPL I had completely forgotten:
BOOST_MPL_ASSERT_MSG
The idea is that you give the macro 3 arguments:
The condition to check
a message (C++ identifier) that should be used for display in the error message
the list of types involved (as a tuple)
It may help considerably in both code self documentation and better error output.
What you are trying to do is to explicitly check whether types passed as template arguments provide the concepts necessary. Short of the concept feature, which was thrown out of C++0X (and thus being one of the main culprits for it becoming C++1X) it's certainly hard to do proper concept checking. Since the 90ies there have been several attempts to create concept-checking libraries without language support, but, basically, all these have achieved is to show that, in order to do it right, concepts need to become a feature of the core language, rather than a library-only feature.
I don't find your ideas of deriving instead of typedef and using enable_if very appealing. As you have said yourself, it often obscures the actual code only for the sake of better compiler error messages.
I find the static assert a lot better. It doesn't require changing the actual code, we all are used to having assertion checks in algorithms and learned to mentally skip over them if we want to understand the actual algorithms, it might produce better error messages, and it will carry over to C++1X better, which is going to have a static_assert (completely with class designer-provided error messages) built in into the language. (I suspect BOOST_STATIC_ASSERT to simply use the built-in static_assert if that's available.)