Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to emulate 'question mark(?)' type generics in Java to C++?

I have a Java code where the return type of a function has unbounded wildcard type (?). How can I emulate something like this in C++? e.g.

    public GroupHandlerSetting<?> handleGroupProcessingFor(final EventHandler<T> eventHandler)
    {
        return new GroupHandlerSetting<T>(eventHandler, eventProcessors);
    }
like image 289
polapts Avatar asked Jun 21 '12 10:06

polapts


People also ask

What does the question mark mean in Java generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

Can you create instances of generic type parameters?

Cannot Instantiate Generic Types with Primitive Types. Cannot Create Instances of Type Parameters.

Are C++ templates and Java generics implemented in the same way?

As to your actual question, how C++ templates are different from Java generics, the answer is that they're really, really different. The languages essentially apply completely different approaches to implementing a similar end effect. Java tends to focus on the definition of the generic.


2 Answers

In C++ all type arguments must have a name, whether you use it or not, so there is no question mark. Just make it a template argument to the function and give it a name and you should be fine.

template <typename T>
struct templ {
   template <typename U>
   void assign( templ<U> & u );      // public void assign<?>( temple<U> u )      
};

That's the trivial part, the more complex part is enforcing constraints on the type, and for that you can use SFINAE:

template <typename T>
struct templ {
   template <typename U, typename _ = std::enable_if< 
                              typename std::is_base_of<U,T>::value
                                       >::type >
   void super( templ<U> & u );       // public void super_<? super T>( templ<?> u )

   template <typename U, typename _ = std::enable_if<
                              typename std::is_base_of<T,U>::value 
                                       >::type >
   void extends( templ<U> & u );     // public void extends_<? extends T>( templ<?> u )
}

That is using C++11 for the SFINAE, in C++03, it is a bit more convoluted (as if this version was simple) as you cannot use SFINAE on a function template argument, so SFINAE needs to be applied to either the return type or extra function arguments. SFINAE is a much more powerful solution, it can be used not only to provide super and extends but with many other features of types or compile time values. Google for SFINAE and you will find many cases of SFINAE being used, many of them will be C++03 style.

There was a proposal for concepts that would have greatly simplified the syntax, but no agreement was reached and in a move to push the standard to completion it was deferred for a later standard.

Now, this is really not that common in C++ as it is in Java, so I recommend that you provide a different question with what you want to do, and you will get ideas for designs in more idiomatic C++.

like image 70
David Rodríguez - dribeas Avatar answered Sep 30 '22 23:09

David Rodríguez - dribeas


Your specific example is easily done, and since I don't use Java, I can't understand why it needs the <?> there. In C++, you just fill in the same template parameter:

template<class T>
GroupHandlerSetting<T> handleGroupProcessingFor(EventHandler<T> const& evHandler){
  return GroupHandlerSetting<T>(evHandler, evProcessors);
}

T will get deduced from whatever argument is passed to handleGroupProcessingFor, and we use just the same T for the return type, basically exactly what you do in the body of the function.

like image 38
Xeo Avatar answered Sep 30 '22 21:09

Xeo