• Advertisement
Sign in to follow this  

[C++] SFINAE

This topic is 3253 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I don't understand why this code doesn't compile. The error is with std::iterator_traits. Compiler says it can't find iterator_category for std::vector which is fine. Therfore the second template should be excluded from matching. Somehow, it casues an error. Any ideas? Don't write that it's not useful. I know it. I'm only testing.
#include <vector>
#include <algorithm>
#include <iterator>

template <typename Cont, typename Cont2>
typename Cont2::iterator copy(const Cont& c, Cont2& dest)
{
    //return std::copy(c.begin(), c.end(), std::back_inserter(dest));
    std::copy(c.begin(), c.end(), std::back_inserter(dest));
    return dest.end();
}

template <typename Cont, typename It>
It copy(const Cont& c, It dest, typename std::iterator_traits<It>::pointer = 0)
{
    return std::copy(c.begin(), c.end(), dest);
}

int main()
{
    std::vector<int> a, b;

    copy(a, b);
}



Comeau errors:
"stl_iterator_base.h", line 110: error: class
          "std::vector<int, std::allocator<int>>" has no member
          "iterator_category"
    typedef typename _Iterator::iterator_category iterator_category;
                                ^
          detected during instantiation of class
                    "std::iterator_traits<_Iterator> [with
                    _Iterator=std::vector<int, std::allocator<int>>]" at line
                    21 of "ComeauTest.c"

"ComeauTest.c", line 21: error: more than one instance of overloaded function "copy"
          matches the argument list, the choices that match are:
            function template "Cont2::iterator copy(const Cont &, Cont2 &)"
            function template "It copy(const Cont &, It,
                      std::iterator_traits<_ForwardIter2>::pointer)"
            The argument types that you used are: (std::vector<int, std::allocator<int>>,
                      std::vector<int, std::allocator<int>>)
      copy(a, b);
      ^
[Edited by - rozz666 on May 29, 2009 7:11:36 AM]

Share this post


Link to post
Share on other sites
Advertisement
I get similar error messages from VC++, but I think they may be red herrings and the real culprit may be:
line 21
error C2668: 'copy' : ambiguous call to overloaded function


Additionally, neither function is a viable candidate for instantiation

template <typename Cont, typename Cont2>
typename Cont2::iterator copy(const Cont& c, Cont2& dest)
{
return std::copy(c.begin(), c.end(), std::back_inserter(dest));
}

causes

error C2664: 'std::_Vector_iterator<_Ty,_Alloc>::_Vector_iterator(const std::_Vector_iterator<_Ty,_Alloc> &)' : 
cannot convert parameter 1 from 'std::back_insert_iterator<_Container>' to 'const std::_Vector_iterator<_Ty,_Alloc> &'

while

template <typename Cont, typename It>
It copy(const Cont& c, It dest, typename std::iterator_traits<It>::pointer = 0)
{
return std::copy(c.begin(), c.end(), dest);
}

causes

error C2039: 'iterator_category' : is not a member of 'std::vector<_Ty>'



HTH

A5

Share this post


Link to post
Share on other sites
The problem seems to be that you are not just checking whether It has a subtype pointer, but trying to instantiate the iterator_traits template which fails because vector doesn't have iterator_category typedef. I don't know if that should be covered by SFINAE.

A solution might be to check for a type that is typedeffed in iterator types directly, and provide a third overload for pointers.


#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

template <typename Cont, typename Cont2>
typename Cont2::iterator copy(const Cont& c, Cont2& dest)
{
std::cout << "Container\n";
std::copy(c.begin(), c.end(), std::back_inserter(dest));
return dest.end();
}

template <typename Cont, typename It>
It copy(const Cont& c, It dest, typename It::iterator_category* = 0)
{
std::cout << "Iterator\n";
return std::copy(c.begin(), c.end(), dest);
}

template <typename Cont, typename Pointer>
Pointer* copy(const Cont& c, Pointer* p)
{
std::cout << "Pointer\n";
return std::copy(c.begin(), c.end(), p);
}

int main()
{
std::vector<int> a, b;
std::vector<int>::iterator it;
int* p;

copy(a, b);
copy(a, it);
copy(a, p);
}



(Or you could just rename one of the overloads - e.g the first might be called append instead - otherwise, if you indeed wanted to copy, you could use vector assignment operator. What kind of a system would it be where you don't know whether you'll end up with an iterator or a container where it would be important for them to be callable in the same way?)

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
Quote:
Original post by rozz666
*bump*


Please do not bump posts in this forum.


Thanks! [smile]


I am not a big friend of bumping (that is, when the bump frequency is higher than 1 bump in 3 days), too, but I think I have the slight memory of another moderator "allowing" it.

Evil Steve, if you hear me, it was not by accident you? Otherwise, all my apologies :|

I fail to find the relevant post right now, though.

Share this post


Link to post
Share on other sites
You may not have noticed but ApochPiQ is now the moderator for General Programming. He is now the guy who determines policy here.

Share this post


Link to post
Share on other sites
@phrensel: Help Wanted allows bumping once every 24 hours. In comparison, bumping once every 1-2 hours here is entirely inappropriate. It's still in the most recent 5-10 threads at that point. The idea behind bumping is to get things visible in the forum once more, and even then, expanding on your question is almost always much preferred -- if you're bumping, presumably there's a reason people aren't answering your question, right?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement