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: Compile time testing for "type equality"? - comp.lang.c++ ...... your requirements more precisely in the template and function parameters to avoid the need for an explicit check: template <class T1, class T2, class I> Alph< std::pair ... std::atomic_bool vs. std::atomic - comp.std.c++... vector depending on the use case 2) you might need to specialize std ... Microsoft Connect As far as I know, the std::atomic<T> template supports a constructor with a parameter ... template template specialization - comp.lang.c++.moderated ...That depends on whether you mean template classes (e.g. std::vector ... DerivedFrom is a template whose parameter is a type. You can't specialize it for a class template; a ... cannot write std::map via ostream_iterator? - comp.lang.c++ ...... and ::operator<< above, can be made into templates. ... Use the new type as a parameter to ostream_iterator. std ... new type cannot be derived from std::pair ... modify map values through an iterator - comp.lang.c++.moderated ...... if you wanted to modify all the values (in the sense of the second template parameter ... > the value_type of the iterator is std::pair<const Key,Value>, the reference ... Forward declaration in with unordered_map - comp.lang.c++ ...... 476: instantiated from ‘std::_Select1st<std::pair<const int ... Instantiating Standard Library templates with incomplete types as type parameters causes the program to ... comp.lang.c++.moderatedIs it acceptable to specialize std::hash direct... Chris ... varies on typename T, I sometimes want a function parameter that has a default of T(): template ... Bad use of stringstream temporary? - comp.lang.c++... deduction rule that only applies to the pattern T&& where T is a template parameter like ... Bad use of stringstream temporary? - comp.lang.c++ std::pair and move-only types ... SOLUTION: compile time array size using type only - comp.lang.c++ ...... with BOOST_STATIC_ASSERT }; //specialize it for array types template<typename T, std ... I can't work out how the value > for template parameter N is determined when all ... Converting number to std::string ("itoa()" ) - comp.lang.c++ ...> You can use std::itoa(), which is a standard C ... just cannot understand that having a pair ... C++, I would rather see an: template< typename T > T atot( std ... c++ - Specialize a class template within a class template? - Stack ...Plus, you can use std::make_pair to avoid repeating the types. ... How to specialize member of template class with template template parameter Partially specialize a template with another template class - C / C++>>>Is it possible to specialize it so that T is a std::pair<A,B> >>>where A and B are new template parameters?[/color] >> >>And where would they come from? 7/18/2012 12:48:17 PM
|