Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Comments

Joshua Burkholder Burkholder
  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @STL:

    Burkholder> http://connect.microsoft.com/VisualStudio/feedback/details/647035/vc-2010-explicit-template-arguments-cause-type-disagreement-for-types-that-decay-to-pointers

    I believe that VC's behavior is CORRECT. Here is a modified repro:

     

    44
    45
    46
    47
    48
    49
    50
    51
     
     
    meow<decltype(f)>(f)
               F: void ()
    decltype(ff): void (*)()
         is_same: false
    meow<void()>(f)
               F: void ()
    decltype(ff): void (*)()
         is_same: false
     


    N3225 7.1.6.2 [dcl.type.simple]/4 says: "The type denoted by decltype(e) is defined as follows: — if e is an unparenthesized id-expression or a class member access (5.2.5), decltype(e) is the type of the entity named by e."

    8.3.5 [dcl.fct]/5 says: "After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively."

    This "adjustment" happens before sizeof (which can easily be verified with arrays adjusted to pointers), so it should happen before decltype too.

    If decltype(ff) has to be adjusted to a pointer type, then why doesn't F also have to be adjusted to a pointer type (regardless of the explicit template arguments) ... like it's adjusted in the implicit template arguments case?

    If (as you are suggesting) this type-disagreement behavior is intended by the standard, then why?  What does this behavior enable?  Or prevent?  I ask because conflicting types ( i.e. F not being the same type as decltype( ff ) even though we declared F ff ) doesn't make much sense to me (esp. if ... say ... F is char[8] and decltype( ff ) adjusts down to char * where sizeof( F ) would be 8 and sizeof( decltype( ff ) ) would be 4 ).

    Joshua Burkholder

     

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @Burkholder:I filed this as a bug on Microsoft's Connect website.  The title of this bug report is "VC++ 2010: Explicit template arguments cause type disagreement for types that decay to pointers" (bug id: 647035) and is under the "Visual Studio and .NET Framework" section.

    Note:  This bug affects anything that decays ... so both function types and array types.  If you start out with say "int arr[3];" and pass arr to those type of functions using implicit and explicit template arguments, then you get the same type of results ... type disagreement ( int[3] versus int * ) when explicit template arguments are used in VC++ 2010, but __no__ type disagreement in g++ 4.5.2.

    Hope This Helps,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    To make this potential VC++ 2010 bug (explicit template argument type disagreement) a little more obvious, here is some much shorter code that pertains just to the bug:

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    template < typename F >
    bool is_F_same_as_decltype_ff ( F ff ) {
        // to suppress unreferenced formal parameter warnings:
        static_cast< void >( ff );
        // check if F is the same as the type of ff
        return is_same< F, decltype( ff ) >::value;
    }
    
    template < typename F >
    bool is_F_same_as_void_void_func_type ( F ) {
        return is_same< F, void () >::value;
    }
    
    template < typename F >
    bool is_F_same_as_ptr_to_void_void_func_type ( F ) {
        return is_same< F, void (*) () >::value;
    }
    
    void f () {
        //
    }
    
    int main () {
        cout << "=================================================" << endl;
        cout << endl;
        // implicit template arguments:
        cout << "is_F_same_as_decltype_ff( f ): ";//vc++: 1, g++: 1
        cout << is_F_same_as_decltype_ff( f ) << endl;
        cout << endl;
        cout << "Is F void ()?     ";//vc++: 0, g++: 0
        cout << is_F_same_as_void_void_func_type( f ) << endl;
        cout << "Is F void (*) ()? ";//vc++: 1, g++: 1
        cout << is_F_same_as_ptr_to_void_void_func_type( f ) << endl;
        cout << endl;
        cout << "=================================================" << endl;
        cout << endl;
        // explicit template arguments:
        cout << "is_F_same_as_decltype_ff< decltype( f ) >( f ): ";//vc++: 0, g++: 1
        cout << is_F_same_as_decltype_ff< decltype( f ) >( f ) << endl;
        cout << endl;
        cout << "Is F void ()?     ";//vc++: 1, g++: 1
        cout << is_F_same_as_void_void_func_type< decltype( f ) >( f ) << endl;
        cout << "Is F void (*) ()? ";//vc++: 0, g++: 0
        cout << is_F_same_as_ptr_to_void_void_func_type< decltype( f ) >( f ) << endl;
        cout << endl;
        cout << "=================================================" << endl;
        cout << endl;
        // ... and just to be extra explicit
        // explicit template arguments:
        cout << "is_F_same_as_decltype_ff< void () >( f ): ";//vc++: 0, g++: 1
        cout << is_F_same_as_decltype_ff< void () >( f ) << endl;
        cout << endl;
        cout << "Is F void ()?     ";//vc++: 1, g++: 1
        cout << is_F_same_as_void_void_func_type< void () >( f ) << endl;
        cout << "Is F void (*) ()? ";//vc++: 0, g++: 0
        cout << is_F_same_as_ptr_to_void_void_func_type< void () >( f ) << endl;
        cout << endl;
        cout << "=================================================" << endl;
    
        return 0;
    }
    On VC++ 2010, this produces the following output:
    =================================================
    
    is_F_same_as_decltype_ff( f ): 1
    
    Is F void ()?     0
    Is F void (*) ()? 1
    
    =================================================
    
    is_F_same_as_decltype_ff< decltype( f ) >( f ): 0
    
    Is F void ()?     1
    Is F void (*) ()? 0
    
    =================================================
    
    is_F_same_as_decltype_ff< void () >( f ): 0
    
    Is F void ()?     1
    Is F void (*) ()? 0
    
    =================================================
    While on g++ 4.5.2, this produces the following output:
    =================================================
    
    is_F_same_as_decltype_ff( f ): 1
    
    Is F void ()?     0
    Is F void (*) ()? 1
    
    =================================================
    
    is_F_same_as_decltype_ff< decltype( f ) >( f ): 1
    
    Is F void ()?     1
    Is F void (*) ()? 0
    
    =================================================
    
    is_F_same_as_decltype_ff< void () >( f ): 1
    
    Is F void ()?     1
    Is F void (*) ()? 0
    
    =================================================
    Since we have F ff as the parameter of the is_F_same_as_decltype_ff() function, it seems like F should __always__ agree with decltype( ff ).  In other words, the bug is that there is type disagreement when explicit template arguments are used (esp. when there is no type disagreement when implicit template arguments are deduced).

    Hope This Clarifies,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @STL:I am a bonehead! ... I finally understand your post ... with a little help from page 168 of "C++ Templates: The Complete Guide".

    Note To Self:  Implicitly deduced template arguments can decay.  Explicit template arguments cannot.

    In my search for clarity, I may have found a **** potential bug **** in VC++ 2010.  Here's the code that helped me out ... I'll explain the potential bug at the end:

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    // decltype( f ): void ()
    void f () {
        //
    }
    
    template< typename F >
    void check_similarity_1 ( F f_ ) {
        static_cast< void >( f_ ); // to eliminate warnings
        // if __implicit__ template argument deduction, then:
        // decltype( f ) decays from void () to void (*) ();
        // therefore, decltype( f_ ) is void (*) () and
        // F is void (*) ()
        cout << "is_same< decltype( f_ ), void () >::value:     "
             << is_same< decltype( f_ ), void () >::value << endl;
        cout << "is_same< decltype( f_ ), void (*) () >::value: "
             << is_same< decltype( f_ ), void (*) () >::value << endl;
        cout << "is_same< decltype( f_ ), void (&) () >::value: "
             << is_same< decltype( f_ ), void (&) () >::value << endl;
        cout << "is_same< F, void () >::value:     "
             << is_same< F, void () >::value << endl;
        cout << "is_same< F, void (*) () >::value: "
             << is_same< F, void (*) () >::value << endl;
        cout << "is_same< F, void (&) () >::value: "
             << is_same< F, void (&) () >::value << endl;
    }
    
    template < typename F >
    void check_similarity_2 ( F * f_ptr ) {
        static_cast< void >( f_ptr ); // to eliminate warnings
        // if __implicit__ template argument deduction, then:
        // decltype( f ) decays from void () to void (*) ();
        // therefore, decltype( f_ptr ) is void (*) () and 
        // F is void ()
        cout << "is_same< decltype( f_ptr ), void () >::value:     "
             << is_same< decltype( f_ptr ), void () >::value << endl;
        cout << "is_same< decltype( f_ptr ), void (*) () >::value: "
             << is_same< decltype( f_ptr ), void (*) () >::value << endl;
        cout << "is_same< decltype( f_ptr ), void (&) () >::value: "
             << is_same< decltype( f_ptr ), void (&) () >::value << endl;
        cout << "is_same< F, void () >::value:     "
             << is_same< F, void () >::value << endl;
        cout << "is_same< F, void (*) () >::value: "
             << is_same< F, void (*) () >::value << endl;
        cout << "is_same< F, void (&) () >::value: "
             << is_same< F, void (&) () >::value << endl;
    }
    
    template < typename F >
    void check_similarity_3 ( F & f_ref ) {
        static_cast< void >( f_ref ); // to eliminate warnings
        // if __implicit__ template argument deduction, then:
        // decltype( f ) goes from void() to void (&) ();
        // therefore, decltype( f_ref ) is void (&) () and
        // F is void ()
        cout << "is_same< decltype( f_ref ), void () >::value:     "
             << is_same< decltype( f_ref ), void () >::value << endl;
        cout << "is_same< decltype( f_ref ), void (*) () >::value: "
             << is_same< decltype( f_ref ), void (*) () >::value << endl;
        cout << "is_same< decltype( f_ref ), void (&) () >::value: "
             << is_same< decltype( f_ref ), void (&) () >::value << endl;
        cout << "is_same< F, void () >::value:     "
             << is_same< F, void () >::value << endl;
        cout << "is_same< F, void (*) () >::value: "
             << is_same< F, void (*) () >::value << endl;
        cout << "is_same< F, void (&) () >::value: "
             << is_same< F, void (&) () >::value << endl;
    }
    
    int main () {
        cout << "main():" << endl;
        cout << "-------" << endl;
        // no __implicit__ template argument deduction ( std::is_same<...> 
        // uses directly deducible, __explicit__ template arguments ); hence, 
        // function types do not decay to pointer types:
        // decltype( f ) is still void () inside of std::is_same<...>
        cout << "is_same< decltype( f ), void () >::value:     "
             << is_same< decltype( f ), void () >::value << endl;
        cout << "is_same< decltype( f ), void (*) () >::value: "
             << is_same< decltype( f ), void (*) () >::value << endl;
        cout << "is_same< decltype( f ), void (&) () >::value: "
             << is_same< decltype( f ), void (&) () >::value << endl;
        cout << endl;
    
        cout << "check_similarity_1( F f_ ):" << endl;
        cout << "---------------------------" << endl;
        check_similarity_1( f );
        cout << endl;
    
        cout << "check_similarity_2( F * f_ptr ):" << endl;
        cout << "--------------------------------" << endl;
        check_similarity_2( f );
        cout << endl;
    
        cout << "check_similarity_3( F & f_ref ):" << endl;
        cout << "--------------------------------" << endl;
        check_similarity_3( f );
        cout << endl;
    
        // Does the following produce a bug in VC++ 2010?
        cout << "check_similarity_1< decltype( f ) >( F f_ ):" << endl;
        cout << "--------------------------------------------" << endl;
        check_similarity_1< decltype( f ) >( f );
        cout << endl;
    
        return 0;
    }
    
    In VC++ 2010, this produces the following output:
    main():
    -------
    is_same< decltype( f ), void () >::value:     1
    is_same< decltype( f ), void (*) () >::value: 0
    is_same< decltype( f ), void (&) () >::value: 0
    
    check_similarity_1( F f_ ):
    ---------------------------
    is_same< decltype( f_ ), void () >::value:     0
    is_same< decltype( f_ ), void (*) () >::value: 1
    is_same< decltype( f_ ), void (&) () >::value: 0
    is_same< F, void () >::value:     0
    is_same< F, void (*) () >::value: 1
    is_same< F, void (&) () >::value: 0
    
    check_similarity_2( F * f_ptr ):
    --------------------------------
    is_same< decltype( f_ptr ), void () >::value:     0
    is_same< decltype( f_ptr ), void (*) () >::value: 1
    is_same< decltype( f_ptr ), void (&) () >::value: 0
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    
    check_similarity_3( F & f_ref ):
    --------------------------------
    is_same< decltype( f_ref ), void () >::value:     0
    is_same< decltype( f_ref ), void (*) () >::value: 0
    is_same< decltype( f_ref ), void (&) () >::value: 1
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    
    check_similarity_1< decltype( f ) >( F f_ ):
    --------------------------------------------
    is_same< decltype( f_ ), void () >::value:     0
    is_same< decltype( f_ ), void (*) () >::value: 1
    is_same< decltype( f_ ), void (&) () >::value: 0
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    In g++ 4.5.2, this code produces the following output:
    main():
    -------
    is_same< decltype( f ), void () >::value:     1
    is_same< decltype( f ), void (*) () >::value: 0
    is_same< decltype( f ), void (&) () >::value: 0
    
    check_similarity_1( F f_ ):
    ---------------------------
    is_same< decltype( f_ ), void () >::value:     0
    is_same< decltype( f_ ), void (*) () >::value: 1
    is_same< decltype( f_ ), void (&) () >::value: 0
    is_same< F, void () >::value:     0
    is_same< F, void (*) () >::value: 1
    is_same< F, void (&) () >::value: 0
    
    check_similarity_2( F * f_ptr ):
    --------------------------------
    is_same< decltype( f_ptr ), void () >::value:     0
    is_same< decltype( f_ptr ), void (*) () >::value: 1
    is_same< decltype( f_ptr ), void (&) () >::value: 0
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    
    check_similarity_3( F & f_ref ):
    --------------------------------
    is_same< decltype( f_ref ), void () >::value:     0
    is_same< decltype( f_ref ), void (*) () >::value: 0
    is_same< decltype( f_ref ), void (&) () >::value: 1
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    
    check_similarity_1< decltype( f ) >( F f_ ):
    --------------------------------------------
    is_same< decltype( f_ ), void () >::value:     1
    is_same< decltype( f_ ), void (*) () >::value: 0
    is_same< decltype( f_ ), void (&) () >::value: 0
    is_same< F, void () >::value:     1
    is_same< F, void (*) () >::value: 0
    is_same< F, void (&) () >::value: 0
    Everything agrees between the output from VC++ 2010 and g++ 4.5.2, except the "check_similarity_1< decltype( f ) >( F f_ )" section ... and there is the potential bug.

    **** potential bug ****:  In VC++ 2010 when I make the call to check_similarity_1< decltype( f ) >( f ) inside of main(), is_same< decltype( f_ ), void (*) () >::value is 1 within that check_similarity_1 function ... even though I explicitly declared the template parameter F to be "void ()" (i.e. decltype( f ) ).  Shouldn't is_same< decltype( f_ ), void () >::value be 1 instead (esp. since is_same< F, void () >::value is 1 within that same function)?  In g++ 4.5.2, is_same< decltype( f_ ), void () >::value is 1.  It seems like VC++ 2010 is assuming that a function argument will always become a pointer ( i.e. "void ()" f will always go to "void (*) ()" f_ ) whether or not it agrees with its actual type ( F: void () ).

    Hope This Helps,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @STL:Looks like we were typing at the same time again!  Wink

    I'm still not sure why the rewriting in the std::is_same<>'s in main isn't taking the function type down to a pointer to function type, but I figured out how to go from "void(*)()" back to "void()" ... which was so simple I'm a little embarrased I asked the question ... just a simple typename std::remove_pointer<...>::type.  Here's the code:

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    void f () {
        //
    }
    
    template < typename F >
    void check_similarity_1 ( F ) {
        cout << "is_same< F, void () >::value:   "
             << is_same< F, void () >::value << endl; // 0
        cout << "is_same< F, void(*)() >::value: "
             << is_same< F, void(*)() >::value << endl; // 1
    }
    
    template < typename F >
    void check_similarity_2 ( F f_ ) {
        static_cast< void >( f_ ); // to eliminate warnings
        cout << "is_same< decltype( f_ ), void () >::value:   "
             << is_same< decltype( f_ ), void () >::value << endl; // 0
        cout << "is_same< decltype( f_ ), void(*)() >::value: "
             << is_same< decltype( f_ ), void(*)() >::value << endl; // 1
    }
    template < typename F >
    void check_similarity_3 ( F ) {
        cout << "is_same< typename remove_pointer< F >::type, void () >::value:   "
             << is_same< typename remove_pointer< F >::type, void () >::value << endl; // 1
        cout << "is_same< typename remove_pointer< F >::type, void(*)() >::value: "
             << is_same< typename remove_pointer< F >::type, void(*)() >::value << endl; // 0
    }
    
    template < typename F >
    void check_similarity_4 ( F f_ ) {
        static_cast< void >( f_ ); // to eliminate warnings
        cout << "is_same< typename remove_pointer< decltype( f_ ) >::type, void () >::value:   "
             << is_same< typename remove_pointer< decltype( f_ ) >::type, void () >::value << endl; // 1
        cout << "is_same< typename remove_pointer< decltype( f_ ) >::type, void(*)() >::value: "
             << is_same< typename remove_pointer< decltype( f_ ) >::type, void(*)() >::value << endl; // 0
    }
    
    int main () {
        cout << "is_same< decltype( f ), void () >::value:   "
             << is_same< decltype( f ), void () >::value << endl; // 1
        cout << "is_same< decltype( f ), void(*)() >::value: "
             << is_same< decltype( f ), void(*)() >::value << endl; // 0
        cout << "is_same< decltype( &f ), void () >::value:   "
             << is_same< decltype( &f ), void () >::value << endl; // 0
        cout << "is_same< decltype( &f ), void(*)() >::value: "
             << is_same< decltype( &f ), void(*)() >::value << endl; // 1
        cout << "is_same< typename remove_pointer< decltype( f ) >::type, void () >::value:   "
             << is_same< typename remove_pointer< decltype( f ) >::type, void () >::value << endl; // 1
        cout << "is_same< typename remove_pointer< decltype( f ) >::type, void(*)() >::value: "
             << is_same< typename remove_pointer< decltype( f ) >::type, void(*)() >::value << endl; // 0
        cout << "is_same< typename remove_pointer< decltype( &f ) >::type, void () >::value:   "
            << is_same< typename remove_pointer< decltype( &f ) >::type, void () >::value << endl; // 1
        cout << "is_same< typename remove_pointer< decltype( &f ) >::type, void(*)() >::value: "
             << is_same< typename remove_pointer< decltype( &f ) >::type, void(*)() >::value << endl; // 0
        check_similarity_1( f );
        check_similarity_2( f );
        check_similarity_3( f );
        check_similarity_4( f );
        return 0;
    }
    
    Here's the output:
    is_same< decltype( f ), void () >::value:   1
    is_same< decltype( f ), void(*)() >::value: 0
    is_same< decltype( &f ), void () >::value:   0
    is_same< decltype( &f ), void(*)() >::value: 1
    is_same< typename remove_pointer< decltype( f ) >::type, void () >::value:   1
    is_same< typename remove_pointer< decltype( f ) >::type, void(*)() >::value: 0
    is_same< typename remove_pointer< decltype( &f ) >::type, void () >::value:   1
    is_same< typename remove_pointer< decltype( &f ) >::type, void(*)() >::value: 0
    is_same< F, void () >::value:   0
    is_same< F, void(*)() >::value: 1
    is_same< decltype( f_ ), void () >::value:   0
    is_same< decltype( f_ ), void(*)() >::value: 1
    is_same< typename remove_pointer< F >::type, void () >::value:   1
    is_same< typename remove_pointer< F >::type, void(*)() >::value: 0
    is_same< typename remove_pointer< decltype( f_ ) >::type, void () >::value:   1
    is_same< typename remove_pointer< decltype( f_ ) >::type, void(*)() >::value: 0

    Thanks For Any Clarification ... And Your Continued Patience Wink,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @STL:Looks like we were both typing at the same time.  Wink  Thank you very much for the explanation!  I'm getting closer to understanding.

    Is there anyway to go from a "void(*)()" back to "void()"?  Or avoid this rewriting?

    Lastly, why is the decltype( f ) in my first couple of std::is_same<...> lines in main() __not__ being rewritten to a pointer to function type once it is inside std::is_same<...>?  In other words, why is the following output being produced from main()?

    is_same< decltype( f ), void () >::value:   1
    is_same< decltype( f ), void(*)() >::value: 0
    is_same< decltype( &f ), void () >::value:   0
    is_same< decltype( &f ), void(*)() >::value: 1 

    Thanks In Advance For Clarification ... And Your Patience With My Dense-ness,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @new2STL:Since void f() isn't always void(*)(), let me clarify.  Why is the first std::is_same<...> in main() returing 1?

    is_same< decltype( f ), void () >::value:   1 
    Similarly, why is the second std::is_same<...> in main() returning 0?
    is_same< decltype( f ), void(*)() >::value: 0
    It seems like this should be 0 then 1 ... like the check_similarity_x() functions, vice 1 then 0.  In order to get a 0 then 1 in main(), I have to do the following:
     #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    void f () {
        //
    }
    
    template < typename F >
    void check_similarity_1 ( F ) {
        cout << "is_same< F, void () >::value:   "
             << is_same< F, void () >::value << endl; // 0
        cout << "is_same< F, void(*)() >::value: "
             << is_same< F, void(*)() >::value << endl; // 1
    }
    
    template < typename F >
    void check_similarity_2 ( F f_ ) {
        static_cast< void >( f_ ); // to eliminate warnings
        cout << "is_same< decltype( f_ ), void () >::value:   "
             << is_same< decltype( f_ ), void () >::value << endl; // 0
        cout << "is_same< decltype( f_ ), void(*)() >::value: "
             << is_same< decltype( f_ ), void(*)() >::value << endl; // 1
    }
    
    int main () {
        cout << "is_same< decltype( f ), void () >::value:   "
             << is_same< decltype( f ), void () >::value << endl; // 1
        cout << "is_same< decltype( f ), void(*)() >::value: "
             << is_same< decltype( f ), void(*)() >::value << endl; // 0
        cout << "is_same< decltype( &f ), void () >::value:   "
             << is_same< decltype( &f ), void () >::value << endl; // 0
        cout << "is_same< decltype( &f ), void(*)() >::value: "
             << is_same< decltype( &f ), void(*)() >::value << endl; // 1
        check_similarity_1( f );
        check_similarity_2( f );
        return 0;
    }
    
    Which produces the following output:
    is_same< decltype( f ), void () >::value:   1
    is_same< decltype( f ), void(*)() >::value: 0
    is_same< decltype( &f ), void () >::value:   0
    is_same< decltype( &f ), void(*)() >::value: 1
    is_same< F, void () >::value:   0
    is_same< F, void(*)() >::value: 1
    is_same< decltype( f_ ), void () >::value:   0
    is_same< decltype( f_ ), void(*)() >::value: 1
    Obviously, this is some rule that I didn't pay enough attention to when I was learning C++ ... or just didn't learn the right way Wink ... I'm just trying to figure out which rule this is.

    Joshua Burkholder

     

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    Why does the decltype of a function change from "void()" to "void(*)()" in the following code?

    Code:

    #include <iostream>
    #include <type_traits>
    
    using namespace std;
    
    void f () {
        //
    }
    
    template < typename F >
    void check_similarity_1 ( F ) {
        cout << "is_same< F, void () >::value:   "
             << is_same< F, void () >::value << endl;// 0
        cout << "is_same< F, void(*)() >::value: "
             << is_same< F, void(*)() >::value << endl;// 1
    }
    
    template < typename F >
    void check_similarity_2 ( F f_ ) {
        static_cast< void >( f_ ); // to eliminate warnings
        cout << "is_same< decltype( f_ ), void () >::value:   "
             << is_same< decltype( f_ ), void () >::value << endl;// 0
        cout << "is_same< decltype( f_ ), void(*)() >::value: "
             << is_same< decltype( f_ ), void(*)() >::value << endl;// 1
    }
    
    int main () {
        cout << "is_same< decltype( f ), void () >::value:   "
             << is_same< decltype( f ), void () >::value << endl;// 1
        cout << "is_same< decltype( f ), void(*)() >::value: "
             << is_same< decltype( f ), void(*)() >::value << endl;// 0
        check_similarity_1( f );
        check_similarity_2( f );
        return 0;
    }
    
    The output of this code on both VC++2010 and g++ 4.5.2 is the following:
    is_same< decltype( f ), void () >::value:   1
    is_same< decltype( f ), void(*)() >::value: 0
    is_same< F, void () >::value:   0
    is_same< F, void(*)() >::value: 1
    is_same< decltype( f_ ), void () >::value:   0
    is_same< decltype( f_ ), void(*)() >::value: 1

    Thanks In Advance For Any Clarification,
    Joshua Burkholder

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @Matt_PD:Thank you so much ... the optimizing_cpp.pdf is OUTSTANDING!

  • C9 Lectures: Stephan T Lavavej - Advanced STL, 1 of n

    @new2stl:Thanks for the information.  I will use the intrin.h header.

    Unfortunately, intrin.h does not seem to exist for GCC's g++ and MinGW's port of g++; however, emmintrin.h exists for both GCC's and MinGW's g++ ... and for Visual C++ 2010.  Here's the simple test that I ran:

    #include <iostream>
    #include <intrin.h>
    //#include <emmintrin.h>
    
    using namespace std;
    
    int main () {
        cout << sizeof( __m128d ) << endl;
        return 0;
    }
    
    ... and here's the command line:
    g++ -o main.exe main.cpp -std=c++0x -march=native -O3 -Wall -Wextra -Werror

    Joshua Burkholder