I
Ivan
How (at compile time) can one determine whether some class implements
a particular member function? Name only is sufficient, full signature
match nice but not required.
The application is a template class that (among other things) defines
an iterator class. The category of iterator depends on the template
argument type: if the argument defines only operator++ then the
iterator will be a forward_iterator, but if it also defines operator--
then the created iterator should be a bidirectional_iterator. That is,
something like this psudocode:
template<typename T> class Foo {
public:
typedef ("T defines --" ? bidirectional_iterator :
forward_iterator) Cat;
class iter : public iterator<..., ..., Cat, ...> {...}
};
The obvious approach is to specialize on the type of T. Unfortunately,
this code is in a general purpose library and the types that might be
the arguments are unknown and probably don't exist yet.
A second obvious approach is to require that the correct
iterator_category be passed in as an explicit argument. Unfortunately,
the requirement for the category is a long way from the library user
interface and asking the user to understand the need and correct value
for this extra argument would be a bit much.
A third approach would be to simply define the richest iterator
category and let it blow up if the actual type did not support
something the user tried to do. Unfortunately other code (STL for
example) will be specialized on the category of the iterators and so
will blow up if wrongly categorized even though it would work with the
correct categorization.
The Boost etc. constraint checking approaches don't work here: they
check for the presence of a concept, but give a compile error if it is
missing, whereas I accept missing without error but want to do
something different in that case.
I have tried to come up with a metaprogram that would do the necessary
test, and failed. The most promising approach was to create a class
that inherited from both the argument T and also from a dummy class
that does define operator-- but with a unique result type. Then a
"typeof(--TEST())" would be either whatever T's operator-- returned,
or the unique dummy type, and the two could be discriminated by
specialization. However, this approach fails because the compiler
throws an ambiguity error when both T and DUMMY have operator--. I
have not been able to create an inheritance tree that forces the
overloading inheritance rules to only pick T (if it has one) without
an ambiguity - ideas?
This cannot be a new problem - how do you do it?
Ivan
a particular member function? Name only is sufficient, full signature
match nice but not required.
The application is a template class that (among other things) defines
an iterator class. The category of iterator depends on the template
argument type: if the argument defines only operator++ then the
iterator will be a forward_iterator, but if it also defines operator--
then the created iterator should be a bidirectional_iterator. That is,
something like this psudocode:
template<typename T> class Foo {
public:
typedef ("T defines --" ? bidirectional_iterator :
forward_iterator) Cat;
class iter : public iterator<..., ..., Cat, ...> {...}
};
The obvious approach is to specialize on the type of T. Unfortunately,
this code is in a general purpose library and the types that might be
the arguments are unknown and probably don't exist yet.
A second obvious approach is to require that the correct
iterator_category be passed in as an explicit argument. Unfortunately,
the requirement for the category is a long way from the library user
interface and asking the user to understand the need and correct value
for this extra argument would be a bit much.
A third approach would be to simply define the richest iterator
category and let it blow up if the actual type did not support
something the user tried to do. Unfortunately other code (STL for
example) will be specialized on the category of the iterators and so
will blow up if wrongly categorized even though it would work with the
correct categorization.
The Boost etc. constraint checking approaches don't work here: they
check for the presence of a concept, but give a compile error if it is
missing, whereas I accept missing without error but want to do
something different in that case.
I have tried to come up with a metaprogram that would do the necessary
test, and failed. The most promising approach was to create a class
that inherited from both the argument T and also from a dummy class
that does define operator-- but with a unique result type. Then a
"typeof(--TEST())" would be either whatever T's operator-- returned,
or the unique dummy type, and the two could be discriminated by
specialization. However, this approach fails because the compiler
throws an ambiguity error when both T and DUMMY have operator--. I
have not been able to create an inheritance tree that forces the
overloading inheritance rules to only pick T (if it has one) without
an ambiguity - ideas?
This cannot be a new problem - how do you do it?
Ivan