C ++ equivalent of using <T extends Class> for java / return type parameter

In java, to create a function that returns an object that is the same type as a parameter and extends a specific class, I would type:

public <T extends MyClass> T foo(T bar) {...} 

Is there a C ++ equivalent?

In other words, how do I create a function that takes any class that extends a specific class and returns the same type? (This is for abstract / pure virtual classes).

+8
java c ++ generics extends
source share
3 answers

We can use enable_if here if you have C ++ 11 or higher

 template<typename T, typename std::enable_if<std::is_base_of<MyClass, T>::value>::type* = nullptr> T Foo(T bar) { return T(); } 

For example:

 class MyClass { public: int a = 1; }; class Derived : public MyClass { public: int b = 2; }; class NotDerived { public: int b = 3; }; template<typename T, typename std::enable_if<std::is_base_of<MyClass, T>::value>::type* = nullptr> T Foo(T bar) { return T(); } int main() { Derived d; NotDerived nd; std::cout << Foo(d).b << std::endl;; // works //std::cout << (Foo(nd)).b << std::endl;; //compiler error return 0; } 

Live demo

+8
source share

Technically, as other answers show, there are ways to limit it to subtypes of a certain type at compile time. However, most of the time you just do

 template <typename T> T foo(T bar) {...} 

without requiring a boundary.

In Java, constraints are required for generics because a generic class or method is compiled separately from any of its uses. Generic classes or methods are compiled once into a single version in bytecode, the only version that can handle any arguments that calling calls throw on them that satisfy the bounds in its declaration.

The compiler must check for types of use of type T in the method body, for example method calls, field calls, etc., without knowing what T , so you must provide a binding so that the compiler can be satisfied that, for example, a method call valid because it is defined for all types that satisfy this binding. For example, if you had the expression bar.baz() in the body of the method, the compiler will allow you to compile if the MyClass type (and therefore all its subtypes) provides the .baz() method; if you have not provided any restrictions, the compiler will complain that Object (the implied upper bound) does not have a .baz() method.

C ++ templates are different. A template class or function is "created" (compiled again) for each other type argument for which it is used. Therefore, during compilation of the function body for a specific T compiler knows what T , and he can directly check the use of this type.

So, if there was a bar.baz() expression in the function body, that would be nice. If you used this function with T as a type that extends MyClass , then it will compile fine, because that type has .baz() . If you use this function with a type that does not have .baz() , then it will not be able to compile when using it. If you accidentally use a function with a type that does not extend MyClass but has .baz() , the type and type of the return type of which correspond to how you use it, it will also compile; but this is not necessarily bad. C ++ templates are usually not used with type hierarchies, but rather with requirements for what the type should provide. So, for example, the sorting algorithm does not require that its container type and / or type extend a certain type, but rather that the container provides certain functions (for example, a random access index operator), and the element type provides certain functions (for example, less than an operator )

+8
source share

Since I cannot comment on the accepted answer, I am providing a new answer that is based on it.

Template parameters can be simplified if the enable_if condition becomes the default type template parameter instead of nullptr .

 template<typename T, typename = std::enable_if<std::is_base_of<MyClass, T>::value>> 
0
source share

All Articles