tags:

views:

674

answers:

6

In Java you can define generic class that accept only types that extends class of your choice, eg:

public class ObservableList<T extends List> {
  ...
}

This is done using "extends" keyword.

Is there some simple equivalent to this keyword in C++?

A: 

Well, you could create your template reading something like this:

template
class ObservableList {
  std::list<T> contained_data;
};

This will however make the restriction implicit, plus you can't just supply anything that looks like a list. There are other ways to restrict the container types used, for example by making use of specific iterator types that do not exist in all containers but again this is more an implicit than an explicit restriction.

To the best of my knowledge a construct that would mirror the statement Java statement to its full extent does not exist in current standard.

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

In C++0x, the introduction of concepts should make this easier but I don't think it'll do exactly what you'd want either.

Timo Geusch
+4  A: 

That's not possible in plain C++, but you can verify template parameters at compile-time through Concept Checking, e.g. using Boost's BCCL.

macbirdie
Well, it *is* possible, but concept checking is still a good idea. :)
j_random_hacker
I actually meant that it was not possible in "plain" C++. ;)
macbirdie
+26  A: 

I suggest using Boost's static assert feature lin concert with is_base_of from the Boost Type Traits library:

template<typename T>
class ObservableList {
    BOOST_STATIC_ASSERT(is_base_of<List, T>::value);
    ...
};

In some other, simpler cases, you can simply forward-declare a global template, but only define (explicitly or partially specialise) it for the valid types:

template<typename T> my_template;     // Declare, but don't define

// int is a valid type
template<> my_template<int> {
    ...
};

// All pointer types are valid
template<typename T> my_template<T*> {
    ...
};

// All other types are invalid, and will cause compiler error messages.
j_random_hacker
Static asserts are nice as well. :)
macbirdie
A: 

Is there some simple equivalent to this keyword in C++?

No.

Depending on what you're trying to accomplish, there might be adequate (or even better) substitutes.

I've looked through some STL code (on linux, I think it's the one deriving from SGI's implementation). It has "concept assertions"; for instance, if you require a type which understands *x and ++x, the concept assertion would contain that code in a do-nothing function (or something similar). It does require some overhead, so it might be smart to put it in a macro whose definition depends on #ifdef debug.

If the subclass relationship is really what you want to know about, you could assert in the constructor that T instanceof list (except it's "spelled" differently in C++). That way, you can test your way out of the compiler not being able to check it for you.

Jonas Kölker
+8  A: 

As far as I know this isn't currently possible in C++. However, there are plans to add a feature called "concepts" in the new C++0x standard that provide the functionallity that you're looking for. This wikipedia article about C++0x will explain concepts in more detail, along with all the features added to C++0x standard.

I know this doesn't fix you're immeadiate problem but there are some C++ compilers that have already started to add features from the new standard so it might be possible to find a compler that has already implemented the concepts feature.

Barry Carr
Concepts have been dropped from the standard unfortunately.
macbirdie
+5  A: 

The simple solution, which no one have mentioned yet, is to just ignore the problem. If I try to use an int as a template type in a function template that expects a container class such as vector or list, then I will get a compile error. Crude and simple, but it solves the problem. The compiler will try to use the type you specify, and if that fails, it generates a compile error.

The only problem with that is that the error messages you get are going to be tricky to read. It is nevertheless a very common way to do this. The standard library is full of function or class templates that expect certain behavior from the template type, and do nothing to check that the types used are valid.

If you want nicer error messages (or if you want to catch cases that wouldn't produce a compiler error, but still don't make sense) you can, depending on how complex you want to make it, use either Boost's static assert or the Boost concept_check library.

jalf
Yes, I always thought that templates are the closest thing to duck typing in C++. If it has all the elements necessary for a template, it can be used in a template.
Arkadiy