Re: Trying to apply SFINAE
On Sep 30, 11:58 am, Hendrik Schober <spamt...@gmx.de> wrote:
James Kanze wrote:
On Sep 29, 6:20 pm, Hendrik Schober <spamt...@gmx.de> wrote:
I'm having two overloaded function templates,
#include <iterator>
template< typename T >
void test( T /*a1*/, T /*a2*/ ) {}
template< typename Iter >
void test( Iter /*b*/, Iter /*e*/ ) {}
which I need to call. (In reality, these are constructors,
in case that matters.)
It could be critical, if you need the initialization list.
The problem is more with your below idea: I cannot
(easily) forward calls.
That's why I raised the issue of initialization lists. That's
the main reason I can think of why you might not be able to
forward calls. (It is, in fact, the only reason I can think of
why you might not be able to forward calls.)
[...]
But of course, since it's undefined behavior to instantiate
iterator_trais with anything that is neither an iterator nor a
pointer, you couldn't count on this even if the type deduction
trick worked.
Is it?
I think so. In =A717.4.3.6/2, it says:
In particular, the effects are undefined in the
following cases:
[...]
-- for types used as template arguments when
instantiating a template component, if the
operations on the type do not implement the
semantics of the applicable Requirements
subclause.[...]
I'm not sure, of course, because the description of Iterator
traits (=A724.3.1) doesn't actually contain a Requirements
subclause. It does require a specific implementation, however
(with a partial specialization for pointers), and that
implementation uses typename Iterator::difference_type, etc. So
the presence of those types in the instantiation type would seem
to be a requirement. (In this regared, the definition of
iterator_category is probably the most significant; I can't
imagine anything but an iterator defining it.)
In practice, what I would expect is that the code would fail to
compile *IF* you use such an instantiation in a context which
requires a complete definition. Or, if that failure occured
during template type deduction, SFINAE. But I couldn't get it
to work.
I thought std lib implementors must have faced this,
but now I see that this
#include <vector>
int main()
{
const unsigned int ua[] = { 255, 255, 255, 255 };
std::vector<int> v1(0u,1u);
std::vector<int> v2(ua, ua+4);
return 0;
}
fails spectacularly with Dinkumware (both call the ctor
taking iterators), so I must be wrong.
The second is required to call the constructor taking iterators.
The first shouldn't, however; the standard says that if the
iterator type (determined by type deduction) is an integral
type, the constructor shall has the same effect as:
X( static_cast< typename X::size_type >( f ),
static_cast< typename X::value_type >( l ) ) ;
(This leads to some interesting, and possibly unintentional
effects, due to the fact that static_cast is an explicit
conversion. Thus:
std::vector< std::vector< int > > v( 10, 30 ) ;
works, although there is no implicit conversion of 30 to
std::vector< int >.)
The version of VC++ (which uses Dinkumware) which I have access
to gets this right. Some older implementations of the library
(Dinkumware or others), designed for compilers which didn't
support member templates, may have problems, however.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34