Is it possible to define two different template (by number of template arguments) classes with the same name?
Here's what I am trying to do:
namespace MyNamespace
{
template<class TRet>
class FunctionObject
{
    typedef typename TRet ReturnType;
    virtual ReturnType const operator()() const = 0;
};
template<class TRet, class TArg0>
class FunctionObject
{
    typedef typename TRet ReturnType;
    typedef typename TArg0 FirstArgumentType;
    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0;
};
}
I get an error mentioning too many template arguments at the end of closing bracket of the second FunctionObject struct definition.
I know this can be done in C#, but wasn't sure about C++. Can someone please shed some light here?
I think partial specialization would do the trick:
namespace MyNamespace {
  template<class TRet, class TArg0>
  class FunctionObject
  {
      typedef typename TRet ReturnType;
      typedef typename TArg0 FirstArgumentType;
      virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0;
  };
  template<class TRet>
  class FunctionObject<TRet,void>
  {
      typedef typename TRet ReturnType;
      virtual ReturnType const operator()() const = 0;
  };
}
You could also start with a primary template with more than one parameter.
I think C++11 its variadic templates allows this to be more nifty, but I hadn't had the time to play with this, so I'd better leave that to someone else to show.
To show sbi's suggested variadic template solution:
namespace MyNamespace {
  template<typename...> FunctionObject;
  template<class TRet, class TArg0>
  class FunctionObject<TRet,TArg0>
  {
      typedef typename TRet ReturnType;
      typedef typename TArg0 FirstArgumentType;
      virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0;
  };
  template<class TRet>
  class FunctionObject<TRet>
  {
      typedef typename TRet ReturnType;
      virtual ReturnType const operator()() const = 0;
  };
}
Now you can add specializations in whatever order you like, without modifying the other templates (unless the number/type of template parameters conflict).
I think you can make it work with one class template, providing default type argument for the second template parameter as:
struct null_type {};
template<class TRet, class TArg0 = null_type>
class FunctionObject
{
    typedef typename TRet ReturnType;
    typedef typename TArg0 FirstArgumentType;
    //both functions here
    virtual ReturnType const operator()() const = 0;
    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0;
};
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With