Can I specialize a template for std::pair parameter?

  • Follow


If I have a template function with one template parameter, is there a
way to specialize or overload it to handle the case where that
parameter is a std::pair?

For example, suppose I have the following function:

  template<typename Entry>
  void WriteEntry(Entry const & entry) {
    std::cout << "[" << entry << "]";
  }

I would like to write a version that takes a std::pair as its
parameter.  (The caller is itself a templated function that iterates
over a std::set or a std::map to write out all its entries in a
specified number of columns.)  However, if I naively write:

  template<typename Left, typename Right>
  void WriteEntry(std::pair<Left, Right> const & entry) {
    std::cout << "[" << entry.first << ", " << entry.second << "]";
  }

then the compiler complains that neither of the two overloads has the
best conversion.

Is there a way to get this to work, or should I be taking a different
approach altogether?  (I can think of a few run-time ways of solving
the problem, but it would be more elegant to deduce which output
function to call at compile time.)


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply palaso (2) 7/7/2005 2:40:06 PM

Matt Young wrote:
> For example, suppose I have the following function:
> 
>   template<typename Entry>
>   void WriteEntry(Entry const & entry) {
>     std::cout << "[" << entry << "]";
>   }
> 
> I would like to write a version that takes a std::pair as its
> parameter.  (The caller is itself a templated function that iterates
> over a std::set or a std::map to write out all its entries in a
> specified number of columns.)  However, if I naively write:
> 
>   template<typename Left, typename Right>
>   void WriteEntry(std::pair<Left, Right> const & entry) {
>     std::cout << "[" << entry.first << ", " << entry.second << "]";
>   }
> 
> then the compiler complains that neither of the two overloads has the
> best conversion.
> 
> Is there a way to get this to work, or should I be taking a different
> approach altogether?  (I can think of a few run-time ways of solving
> the problem, but it would be more elegant to deduce which output
> function to call at compile time.)

I just used your code with

int main()
{
     WriteEntry(42);
     WriteEntry(std::pair<int,int>(42,84));

     return 0;
}

my compilers did not complain or warn. g++ 3.4.2 and 4.0.0, -Wall.

-- 
A. Kanawati
NO.antounk.SPAM@comcast.net

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Antoun 7/8/2005 12:42:04 AM


This is an overload, not specialization. One cannot specialize function
templates, this is prohibited by the Holy Standard :)

I examined following code:
#include <iostream>
#include <utility>
#include <typeinfo>

template<class T> char* foo(const T& t)
{
  std::cout << "generic foo of " << typeid(t).name() << "\n";
  return "x";
}
template<class T, class U> int foo(const std::pair<T,U>& t)
{
  std::cout << "specific foo of " << typeid(t).name() << "\n";
  return 0;
}
int main()
{
  char *x = foo(123); // generic
  int   y = foo(std::make_pair(1,2)); // specific
}

Comeau 4.3.3 online ( www.comeaucomputing.com/tryitout |
www.nixie.narod.ru/comeau ) compiled this,
while VC 6 sp6 failed, reporting "ambiguous call, none of overloads,
etc."

So, this is a problem of the compiler you use.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kodt 7/8/2005 1:00:03 AM

If you are allowed to change a signature of your template, here is a
way to solve it:

template<class T>
void foo(T t, char dummy) // a prototype uses 'char'
{
  cout << "base: " << typeid(t).name();
}

template<class T, class U>
void foo(pair<T,U> t, int dummy) // all quazy-specializations shall use
'int'
{
  cout << "pair: " << typeid(t).name();
}

template<class T>
void foo(T t)
{
  foo(t,0); // specialization is preferred because it doesn't require
additional type conversion (int->char)
}


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kodt 7/8/2005 1:02:03 AM

"Matt Young" <palaso@gmail.com> writes:

> If I have a template function with one template parameter, is there
> a way to specialize or overload it to handle the case where that
> parameter is a std::pair?

Yes. Not directly though.


> For example, suppose I have the following function:
>
>   template<typename Entry>
>   void WriteEntry(Entry const & entry) {
>     std::cout << "[" << entry << "]";
>   }
>
> I would like to write a version that takes a std::pair as its
> parameter.  (The caller is itself a templated function that iterates
> over a std::set or a std::map to write out all its entries in a
> specified number of columns.)  However, if I naively write:
>
>   template<typename Left, typename Right>
>   void WriteEntry(std::pair<Left, Right> const & entry) {
>     std::cout << "[" << entry.first << ", " << entry.second << "]";
>   }
>
> then the compiler complains that neither of the two overloads has
> the best conversion.

This is overloading, not specialization (just for the record; I assume
you know that).


> Is there a way to get this to work, or should I be taking a different
> approach altogether?  (I can think of a few run-time ways of solving
> the problem, but it would be more elegant to deduce which output
> function to call at compile time.)

Delegate to a static member function of a template, which you can
partially specialize. E.g.:

template <typename T>
struct EntryWriter
{
  static void write(T const &entry)
  {
    std::cout << "[" << entry << "]";
  }
};

template <typename T1, typename T2>
struct EntryWriter< std::pair<T1,T2> >
{
  static void write(std::pair<T1,T2> const &entry)
  {
    std::cout << "[" << entry.first << ", " << entry.second << "]";
  }
};

template<typename T>
void WriteEntry(T const &entry) {
  EntryWriter<T>::write(entry);
}

int main()
{
  WriteEntry(6);
  WriteEntry(std::make_pair(7,8));
}

Since we have specialization here, EntryWriter< std::pair<T1,T2> >
will be preferred if T is a specialization of std::pair.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Thomas 7/8/2005 1:10:33 AM

Matt Young <palaso@gmail.com> wrote:
> If I have a template function with one template parameter, is there a
> way to specialize or overload it to handle the case where that
> parameter is a std::pair?

You can't specialise for std::pair - that would be a partial
specialisation, and those don't exist for function templates.
You can overload, though.

> For example, suppose I have the following function:
>
>   template<typename Entry>
>   void WriteEntry(Entry const & entry) {
>     std::cout << "[" << entry << "]";
>   }
>
> I would like to write a version that takes a std::pair as its
> parameter.  (The caller is itself a templated function that iterates
> over a std::set or a std::map to write out all its entries in a
> specified number of columns.)  However, if I naively write:
>
>   template<typename Left, typename Right>
>   void WriteEntry(std::pair<Left, Right> const & entry) {
>     std::cout << "[" << entry.first << ", " << entry.second << "]";
>   }
>
> then the compiler complains that neither of the two overloads has the
> best conversion.
<snip>

I think your compiler is in error.  The code you've posted compiles
without error in VC++ 7.1, Comeau C++ 4.3.3 beta, g++ 3.3 and 3.4.

Ben.

-- 
Ben Hutchings
Having problems with C++ templates?  Your questions may be answered by
<http://womble.decadentplace.org.uk/c++/template-faq.html>.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ben 7/8/2005 1:15:02 AM

VC6 (I believe Matt Young uses it) doesn't support partial
specialization.
Good compilers have no problems with both overloading of function
templates and partial specialization of class templates.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kodt 7/8/2005 10:32:12 AM

6 Replies
122 Views

(page loaded in 0.072 seconds)

Similiar Articles:













7/18/2012 12:48:17 PM


Reply: