views:

440

answers:

5

Is there equivalent of <? extends T> <? super T> in c++?
Also, does <? extends T> <? super T> work even if T is an interface in Java?

+2  A: 

To answer your second question: yes. As far as generics is concerned, interfaces are treated the same as real classes.

I'll leave the first question to the more C++-savvy people.

JesperE
A: 

answer to the first part: http://stackoverflow.com/questions/148373/c-restrict-template-function

JasperE has the answer right for the 2nd part.

TofuBeer
Following the rule that if class passed as argument has the necessary methods defined is the a fool-proof check. An approved class will definitely have all the necessary functions. But the reverse is not always true. If you have something like <? extends T> then it is fool-proof because we are explicitly specifying the class hierarchy
ajay
@ajay: If you want to restrict type parameter to being a base class because you use exactly the base class interface, then do you need to make it a template? Can you operate on a base class by reference? This would gain you the type safety that you are looking for. Templates allow you do define operations that work across types that don't have to be from the same hierarchy. That is their power. If this isn't feasible in your situation, perhaps you could update the question with more details about what you are trying to do and what C++ features might help you achieve that.
Charles Bailey
? extends means any subclass of the basetype.
TofuBeer
@ajay: You should protect your code against Murphy, not Machiavelli. ;) You have to trust that if I instantiate your template with a type T, then T satisifes the requirements you place on it.Even if you forced my type T to be derived from a specific base class, that'd still only buy you limited protection. I can still define any virtual function to do *anything* I like, whether or not it's meaningful in your case.
jalf
@Charles: the point of using `? extends T` is not as a type of arguments themselves, it's to specialize collections/containers. Consider if you want a function that takes as an argument a list of some objects which all inherit from `Base`. In Java, you write it as `void foo(List<? extends Base> lst)`. In C++, you'd need something like `template<class T> void foo(std::list<T> lst)`.
Pavel Minaev
+3  A: 

It doesn't have quite nice syntactic sugar as in Java but it's manageable well with *boost/type_traits* . See http://www.boost.org/doc/libs/1%5F40%5F0/libs/type%5Ftraits/doc/html/index.html for more info.

#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

class Base {};
class Derived_from_Base : public Base {};
class Not_derived_from_Base {};

template<typename BASE, typename DERIVED>
void workOnBase()
{
    BOOST_STATIC_ASSERT((boost::is_base_of<BASE, DERIVED>::value)); 
}

int main()
{
    workOnBase<Base, Derived_from_Base>();     // OK
    workOnBase<Base, Not_derived_from_Base>(); // FAIL
    return 0;
}

1>d:...\main.cpp(11) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE' 1> with 1> [ 1> x=false 1> ]

pprzemek
+2  A: 

You can restrict the range of a template parameter in C++ using the various traits mechanisms, of which there are implementations available in boost.

Usually you don't - the reason the syntax exists in Java and C# is that they use generics, not templates.

Java generics generate shared code which uses virtual dispatch from the base type, rather than generating code for each type used as a template argument. So usually you are using the restriction in order to allow you to call methods on objects of the type used as the template parameter.

As C++ generates code for each type used as a template parameter, it doesn't need to know about a base type for them.

For example, a template class for a matrix will use +,-,* operators on its target type. In can then be used for any type which supports those operators. If it was arbitrarily restricted to doubles and ints, then you couldn't use the template with a complex<double> or run a test with a type which supports interval arithmetic, even though those types provide those operators, and the matrix library would be valid using them.

The ability to work on arbitrary types which have the same shape is the power of templates, and makes them more useful. It's up to the client code to decide whether or not it's valid to use that template with that type (as long as it compiles), and the customer is always right. The inability to work on arbitrary types which have the same shape, and the requirement to specify restrictions to call methods other than those of java.lang.Object is a weakness of generics.

Pete Kirkham
+2  A: 

This is an extension that sadly was removed from the draft standard of C++0x as it "was not ready". However, it is possible to simulate this using static asserts (that is a part of C++0x and Boost as people have mentioned here).

larsm