Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Special case of templates, pointers-to-members, inheritance - works in VC++ 2008, GCC 3.4.4, but fails in VC++ 2005

Special case of templates, pointers-to-members, inheritance - works in VC++ 2008, GCC 3.4.4, but fails in VC++ 2005

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++wpfoop
3 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kosta Cherry
    wrote on last edited by
    #1

    Hi All, I'm hitting my head against the wall third day about the following code:

    //#define PointerToMember(B) B::*
    #define PointerToMember(B)

    template <bool A, typename B, typename C, C PointerToMember(B) D>
    class One
    {
    public:
    One() {};
    };

    template <typename B, typename C, C PointerToMember(B) D>
    class One<true, B, C, D> : public One<false, B, C, D>
    {
    public:
    One<true, B, C, D>() : One<false, B, C, D>() { };
    };

    template <bool A, typename B>
    struct Two
    {
    template <typename C, C PointerToMember(B) D>
    class OneUsage : public One<A, B, C, D> { };
    };

    template <typename B>
    struct Two<true, B> : public Two<false, B>
    {
    template <typename C, C PointerToMember(B) D>
    class OneUsage : public One<true, B, C, D> { };

    };

    struct S { int i;};

    int main()
    {
    //Two<true, S>::OneUsage<int, &S::i> two;
    Two<true, S>::OneUsage<int, 1> two;
    return 0;
    }

    With those two lines commented out, it compiles in all 3 compilers: GCC, VC++ 2008 and VC++ 2005. But, if instead of

    //#define PointerToMember(B) B::*
    #define PointerToMember(B)
    ...
    //Two<true, S>::OneUsage<int, &S::i> two;
    Two<true, S>::OneUsage<int, 1> two;

    you will make it this:

    #define PointerToMember(B) B::*
    //#define PointerToMember(B)
    ...
    Two<true, S>::OneUsage<int, &S::i> two;
    //Two<true, S>::OneUsage<int, 1> two;

    it still will compile in GCC and 2008, but will fail in 2005 with error: error C2955: 'Two<A,B>::OneUsage' : use of class template requires template argument list with [ A=true, B=S ] list4.cpp(30) : see declaration of 'Two<A,B>::OneUsage' with [ A=true, B=S ] error C2133: 'two' : unknown size error C2512: 'Two<A,B>::OneUsage' : no appropriate default constructor available with [ A=true, B=S ] Looks like VC++ 2005 compiler does not like usage of pointer-to-member type declaration when inheriting templates with partial specialization. Is it a bug of VC++ 2005, or I break some C++ standard, and other two compilers are just more forgiving? This code was taken from much more complex one just to show exact problem. Code compiled by both VC++ 2008 and GCC works with no issue and as

    K A 2 Replies Last reply
    0
    • K Kosta Cherry

      Hi All, I'm hitting my head against the wall third day about the following code:

      //#define PointerToMember(B) B::*
      #define PointerToMember(B)

      template <bool A, typename B, typename C, C PointerToMember(B) D>
      class One
      {
      public:
      One() {};
      };

      template <typename B, typename C, C PointerToMember(B) D>
      class One<true, B, C, D> : public One<false, B, C, D>
      {
      public:
      One<true, B, C, D>() : One<false, B, C, D>() { };
      };

      template <bool A, typename B>
      struct Two
      {
      template <typename C, C PointerToMember(B) D>
      class OneUsage : public One<A, B, C, D> { };
      };

      template <typename B>
      struct Two<true, B> : public Two<false, B>
      {
      template <typename C, C PointerToMember(B) D>
      class OneUsage : public One<true, B, C, D> { };

      };

      struct S { int i;};

      int main()
      {
      //Two<true, S>::OneUsage<int, &S::i> two;
      Two<true, S>::OneUsage<int, 1> two;
      return 0;
      }

      With those two lines commented out, it compiles in all 3 compilers: GCC, VC++ 2008 and VC++ 2005. But, if instead of

      //#define PointerToMember(B) B::*
      #define PointerToMember(B)
      ...
      //Two<true, S>::OneUsage<int, &S::i> two;
      Two<true, S>::OneUsage<int, 1> two;

      you will make it this:

      #define PointerToMember(B) B::*
      //#define PointerToMember(B)
      ...
      Two<true, S>::OneUsage<int, &S::i> two;
      //Two<true, S>::OneUsage<int, 1> two;

      it still will compile in GCC and 2008, but will fail in 2005 with error: error C2955: 'Two<A,B>::OneUsage' : use of class template requires template argument list with [ A=true, B=S ] list4.cpp(30) : see declaration of 'Two<A,B>::OneUsage' with [ A=true, B=S ] error C2133: 'two' : unknown size error C2512: 'Two<A,B>::OneUsage' : no appropriate default constructor available with [ A=true, B=S ] Looks like VC++ 2005 compiler does not like usage of pointer-to-member type declaration when inheriting templates with partial specialization. Is it a bug of VC++ 2005, or I break some C++ standard, and other two compilers are just more forgiving? This code was taken from much more complex one just to show exact problem. Code compiled by both VC++ 2008 and GCC works with no issue and as

      K Offline
      K Offline
      Kosta Cherry
      wrote on last edited by
      #2

      OK, question still remains, but I solved the problem by moving declaration of pointer-to-member this way:

      //#define PointerToMember(B) B::*
      #define PointerToMember(B)

      Two<true, S>::OneUsage<int S::*, &S::i> two;
      //Two<true, S>::OneUsage<int, 1> two;

      Pay attention to this line:

      Two<true, S>::OneUsage<int S::*, &S::i> two;

      Basically, instead of saying to template in the declaration that passed variable is of type pointer-to-member, I just make typename "C" to be pointer-to-int-member. Problem with this is that now I don't know the final type of variable "D", and if I will ever need it, I would need to pass it separately, i.e. adding one more template parameter. This variant compiles everywhere, but question still remains: what's wrong with previous one? It's more compact and straightforward...

      1 Reply Last reply
      0
      • K Kosta Cherry

        Hi All, I'm hitting my head against the wall third day about the following code:

        //#define PointerToMember(B) B::*
        #define PointerToMember(B)

        template <bool A, typename B, typename C, C PointerToMember(B) D>
        class One
        {
        public:
        One() {};
        };

        template <typename B, typename C, C PointerToMember(B) D>
        class One<true, B, C, D> : public One<false, B, C, D>
        {
        public:
        One<true, B, C, D>() : One<false, B, C, D>() { };
        };

        template <bool A, typename B>
        struct Two
        {
        template <typename C, C PointerToMember(B) D>
        class OneUsage : public One<A, B, C, D> { };
        };

        template <typename B>
        struct Two<true, B> : public Two<false, B>
        {
        template <typename C, C PointerToMember(B) D>
        class OneUsage : public One<true, B, C, D> { };

        };

        struct S { int i;};

        int main()
        {
        //Two<true, S>::OneUsage<int, &S::i> two;
        Two<true, S>::OneUsage<int, 1> two;
        return 0;
        }

        With those two lines commented out, it compiles in all 3 compilers: GCC, VC++ 2008 and VC++ 2005. But, if instead of

        //#define PointerToMember(B) B::*
        #define PointerToMember(B)
        ...
        //Two<true, S>::OneUsage<int, &S::i> two;
        Two<true, S>::OneUsage<int, 1> two;

        you will make it this:

        #define PointerToMember(B) B::*
        //#define PointerToMember(B)
        ...
        Two<true, S>::OneUsage<int, &S::i> two;
        //Two<true, S>::OneUsage<int, 1> two;

        it still will compile in GCC and 2008, but will fail in 2005 with error: error C2955: 'Two<A,B>::OneUsage' : use of class template requires template argument list with [ A=true, B=S ] list4.cpp(30) : see declaration of 'Two<A,B>::OneUsage' with [ A=true, B=S ] error C2133: 'two' : unknown size error C2512: 'Two<A,B>::OneUsage' : no appropriate default constructor available with [ A=true, B=S ] Looks like VC++ 2005 compiler does not like usage of pointer-to-member type declaration when inheriting templates with partial specialization. Is it a bug of VC++ 2005, or I break some C++ standard, and other two compilers are just more forgiving? This code was taken from much more complex one just to show exact problem. Code compiled by both VC++ 2008 and GCC works with no issue and as

        A Offline
        A Offline
        Aescleal
        wrote on last edited by
        #3

        I can't comment on what's wrong with your code in the context of VC++2005 - I don't tend to use pointers to members much and never as template arguments. However as your code is compiling and working on two other compilers I'd put it down to VC++2005 not being standard compliant in that area. I'd be tempted to try VC++2010, gcc 4.x and an EDG based as well and see what happens. If those three work then you can be fairly sure your code is standard. One other point - templates with templated internal types are going to confuse most people. Make sure you keep a clean interface between your code and your users or they're going to end up cursing your name. Something like bind_first or make_pair to hide all the gribbly declarations they might otherwise have to make (and which are a godsend with C++0x and the auto keyword). Cheers, Ash

        modified on Thursday, July 8, 2010 4:03 AM

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • World
        • Users
        • Groups