Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


[C++] SFINAE


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 rozz666   Members   -  Reputation: 669

Like
0Likes
Like

Posted 28 May 2009 - 08:54 PM

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]

Sponsor:

#2 rozz666   Members   -  Reputation: 669

Like
0Likes
Like

Posted 28 May 2009 - 10:30 PM

*bump*


#3 rozz666   Members   -  Reputation: 669

Like
0Likes
Like

Posted 29 May 2009 - 12:20 AM

*bump*

#4 Amnesiac5   Members   -  Reputation: 157

Like
0Likes
Like

Posted 29 May 2009 - 12:50 AM

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

#5 rozz666   Members   -  Reputation: 669

Like
0Likes
Like

Posted 29 May 2009 - 01:13 AM

I fixed the error. Nevertheless, the first function is a viable candidate.

#6 visitor   Members   -  Reputation: 643

Like
0Likes
Like

Posted 29 May 2009 - 03:06 AM

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?)

#7 ApochPiQ   Moderators   -  Reputation: 17475

Like
0Likes
Like

Posted 29 May 2009 - 03:12 AM

Quote:
Original post by rozz666
*bump*


Please do not bump posts in this forum.


Thanks! [smile]

#8 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 29 May 2009 - 03:38 AM

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.

#9 SiCrane   Moderators   -  Reputation: 10378

Like
0Likes
Like

Posted 29 May 2009 - 04:13 AM

You may not have noticed but ApochPiQ is now the moderator for General Programming. He is now the guy who determines policy here.

#10 MaulingMonkey   Members   -  Reputation: 1556

Like
0Likes
Like

Posted 29 May 2009 - 06:40 AM

@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?

#11 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 29 May 2009 - 08:05 AM

Quote:
Original post by SiCrane
You may not have noticed but ApochPiQ is now the moderator for General Programming. He is now the guy who determines policy here.


Then it was a misunderstanding from my side about "this forum" meaning "general programming forum" and not "gamedev.net forum(s)". Though I think it can be confusing to have different policies for each forum, but that probably has reasons; otoh my question is now answered and for the rest I don't really care as I never bump :D


Quote:
Original post by MaulingMonkey
@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?


Yes, full agree. As I said, I don't care as long as the bump frequency is a bump every 3 days or so.

#12 ApochPiQ   Moderators   -  Reputation: 17475

Like
0Likes
Like

Posted 29 May 2009 - 08:12 AM

Quote:
Original post by phresnel
Then it was a misunderstanding from my side about "this forum" meaning "general programming forum" and not "gamedev.net forum(s)". Though I think it can be confusing to have different policies for each forum, but that probably has reasons; otoh my question is now answered and for the rest I don't really care as I never bump :D


Yeah, I know it gets hard to keep track of who allows what in which fora. That's why I posted a friendly message in the thread instead of bringing out the banhammer [wink]

#13 Zahlman   Moderators   -  Reputation: 1682

Like
0Likes
Like

Posted 29 May 2009 - 10:01 AM

Quote:
Original post by rozz666
*bump*


You don't need to bump your thread every two hours. Even in General Programming, a thread will usually stay on the first page for a day or so. At the time of your bumpings, most users in North America (which account for a lot of the user base, as you can imagine) would have been asleep.

#14 loufoque   Banned   -  Reputation: 93

Like
0Likes
Like

Posted 29 May 2009 - 07:31 PM

Or you can just disable the second overload if It has a iterator typedef, which should be enough to lever ambiguity.

BOOST_MPL_HAS_XXX_TRAIT_DEF(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>
typename boost::disable_if<
has_iterator<It>,
It
>::type
copy(const Cont& c, It dest)
{
return std::copy(c.begin(), c.end(), dest);
}


In case you don't want to use boost enable_if or boost.mpl has_xxx, you can simply rewrite them.
has_xxx requires a trick or two though.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS