partial ordering of overloaded function templates

J

John Harrison

I've tried the following program on two different compilers (VC++ 7.1 and
gcc 3.3.1) and both print "first" when I expected "second". Why is that?

#include <vector>
#include <iostream>

template <class Iter>
void func(Iter i)
{
std::cout << "first\n";
}

template <class T>
void func(typename std::vector<T>::iterator i)
{
std::cout << "second\n";
}

int main()
{
std::vector<int> v;
func(v.begin());
}

john
 
J

John Harrison

John Harrison said:
I've tried the following program on two different compilers (VC++ 7.1 and
gcc 3.3.1) and both print "first" when I expected "second". Why is that?
template <class T>
void func(typename std::vector<T>::iterator i)

OK, I've figured it out, 'std::vector<T>::iterator' is a non-deduced
context. Annoying.

john
 
R

Rob Williscroft

John Harrison wrote in in comp.lang.c++:
I've tried the following program on two different compilers (VC++ 7.1 and
gcc 3.3.1) and both print "first" when I expected "second". Why is that?

Because the second is non-deducable.

Its non-deducable because the standard says so.
template <class T>
void func(typename std::vector<T>::iterator i)
{
std::cout << "second\n";
}

The good news is: its non-deducable :), which can be exploited:


If the news link doesn't work: http://tinyurl.com/2smov

Rob.
 
G

Gianni Mariani

John said:
I've tried the following program on two different compilers (VC++ 7.1 and
gcc 3.3.1) and both print "first" when I expected "second". Why is that?

#include <vector>
#include <iostream>

template <class Iter>
void func(Iter i)
{
std::cout << "first\n";
}

template <class T>
void func(typename std::vector<T>::iterator i)
{
std::cout << "second\n";
}

int main()
{
std::vector<int> v;
func(v.begin());
}

Function member type resolution you're looking for is not allowed
(because in many cases it is ambiguous).

You *might* be able to do somthing like the example below. This may not
compile on all compilers. I recently found a number of bugs in gcc and
VC++ in this area (Comeau got it right - again!). gcc 3.4.0 appears to
compile this fine.


#include <vector>
#include <list>
#include <iostream>


template <bool v>
struct Helper
{
};

template <typename T1, typename T2>
struct IsSameType
{
static const bool value = false;
};

template <typename T>
struct IsSameType<T, T>
{
static const bool value = true;
};


template <class T>
void func(
const T & v,
Helper<
IsSameType<
T,
typename std::vector said:
::value
* x
)
{
std::cout << "second\n";
}

struct Y
{
};

template <class Iter>
struct X
: Y
{
};

template <class Iter>
void func(Iter i, ... )
{
std::cout << "first\n";
}

int main()
{
std::vector<int> v;
func(v.begin(), static_cast< Helper<true> * >( 0 ) );
std::list<int> x;
func(x.begin(), static_cast< Helper<true> * >( 0 ) );
}
 
H

Howard Hinnant

John Harrison said:
OK, I've figured it out, 'std::vector<T>::iterator' is a non-deduced
context. Annoying.

john

Here is something that you can try, works with Metrowerks:

#include <vector>
#include <iostream>

template <class Iter>
typename Metrowerks::restrict_to
<
!Metrowerks::is_same
<
Iter,
typename std::vector<typename
std::iterator_traits said:
::value, void
::type
func(Iter i)
{
std::cout << "first\n";
return (void)0;
}

template <class Iter>
typename Metrowerks::restrict_to
<
Metrowerks::is_same
<
Iter,
typename std::vector<typename
std::iterator_traits said:
::value, void
::type
func(Iter i)
{
std::cout << "second\n";
return (void)0;
}

int main()
{
std::vector<int> v;
func(v.begin());
}

Metrowerks::restrict_to is the same things as boost::enable_if (
http://www.boost.org/libs/utility/enable_if.html ).

-Howard
 
J

John Harrison

John Harrison said:
I've tried the following program on two different compilers (VC++ 7.1 and
gcc 3.3.1) and both print "first" when I expected "second". Why is that?

#include <vector>
#include <iostream>

template <class Iter>
void func(Iter i)
{
std::cout << "first\n";
}

template <class T>
void func(typename std::vector<T>::iterator i)
{
std::cout << "second\n";
}

int main()
{
std::vector<int> v;
func(v.begin());
}

john

Thanks for the suggested workarounds. Unfortunately the code I posted bears
little relation to my real code so they aren't applicable, interesting
though. Fortunately though once I realised what the problem was I had a
different way to solve this.

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top