Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class templates with duplicate names?

Tags:

c++

templates

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?

like image 483
Engineer007 Avatar asked Feb 27 '12 17:02

Engineer007


3 Answers

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.

like image 133
sbi Avatar answered Oct 29 '22 05:10

sbi


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).

like image 25
bames53 Avatar answered Oct 29 '22 05:10

bames53


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;
};
like image 28
Nawaz Avatar answered Oct 29 '22 04:10

Nawaz