SFINAE compiler troubles

前端 未结 5 848
一向
一向 2021-02-06 08:54

The following code of mine should detect whether T has begin and end methods:

template 
struct is_contai         


        
5条回答
  •  渐次进展
    2021-02-06 09:37

    So, here's how I go about debugging these things.

    First, comment out the negative alternative so you get an error instead of just a mismatch. Next, try to instantiate the type you're putting in the function with one of the items that do not work.

    At this step, I was able to instantiate your sfinae object but it still wasn't working. "This lets me know it IS a VS bug, so the question then is how to fix it." -- OBS

    VS seems to have troubles with SFINAE when done the way you are. Of course it does! It works better when you wrap up your sfinae object. I did that like so:

    template 
    struct sfinae 
    {
      // typedef typename U::const_iterator it_t; - fails to compile with non-cont types.  Not sfinae
      template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
      struct type_ {};
    
      typedef type_ type;
    };
    

    Still wasn't working, but at least I got a useful error message:

    error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::_Tree_const_iterator<_Mytree> (__thiscall std::set<_Kty>::* )(void) const'

    This lets me know that &U::end is not sufficient for VS (ANY compiler) to be able to tell which end() I want. A static_cast fixes that:

      typedef type_(&U::begin),static_cast(&U::end)> type;
    

    Put it all back together and run your test program on it...success with VS2010. You might find that a static_cast is actually all you need, but I left that to you to find out.

    I suppose the real question now is, which compiler is right? My bet is on the one that was consistent: g++. Point to the wise: NEVER assume what I did back then.

    Edit: Jeesh... You are wrong!

    Corrected version:

    template 
    struct is_container
    {
        template  
        struct sfinae 
        {
          //typedef typename U::const_iterator it_t;
          template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
          struct type_ {};
    
          typedef type_(&U::begin),static_cast(&U::end)> type;
        };
    
        template  static char test(typename sfinae::type*);
        template  static long test(...);
    
        enum { value = (1 == sizeof test(0)) };
    };
    
    
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
        std::cout << is_container >::value << ' ';
        std::cout << is_container >::value << ' ';
        std::cout << is_container >::value << ' ';
        std::cout << is_container >::value << ' ';
        std::cout << is_container::value << '\n';
    }
    

    -- The debugging above is sensible, but the assumption about the compiler was wrong headed. G++ should have failed for the reason I emphasized above.

提交回复
热议问题