Indexer on generic argument

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • christian2.schmidt@gmx.de

    Indexer on generic argument

    Hi,
    why does the first Console::Write give error "indexer needs array or
    pointer" and the second not?

    generic <typename TList, typename ItemTypewhere TList :
    IList<ItemType>
    ref class MyClass
    {
    public:
    MyClass() {}
    void Method(TList list1)
    {
    Console::Write( "{0}, ", list1[0]); // error C2109 ??
    IList<ItemType> ^ list2 = list1;
    Console::Write( "{0}, ", list2[0]); // ok
    }
    };

    Cheers,
    Christian
  • Pavel Minaev

    #2
    Re: Indexer on generic argument

    On Aug 5, 9:22 pm, christian2.schm ...@gmx.de wrote:
    why does the first Console::Write give error "indexer needs array or
    pointer" and the second not?
    >
    generic <typename TList, typename ItemTypewhere TList :
    IList<ItemType>
    ref class MyClass
    {
    public:
            MyClass() {}
            void Method(TList list1)
            {
                    Console::Write( "{0}, ", list1[0]); // error C2109 ??
                    IList<ItemType> ^ list2 = list1;
                    Console::Write( "{0}, ", list2[0]); // ok
            }
    >
    };
    I can't figure out why it should be any different, but specifying the
    indexer property explicitly works:

    Console::Write( "{0}, ", list1->default[0]);

    Since there's no real reason why it shouldn't be able to figure out
    the default property when the short form is used (after all, it can do
    it for types which are not generic type parameters just fine!), it's
    probably worth opening a suggestion on VS Connect regarding this.

    Comment

    • Ben Voigt [C++ MVP]

      #3
      Re: Indexer on generic argument

      Pavel Minaev wrote:
      On Aug 5, 9:22 pm, christian2.schm ...@gmx.de wrote:
      >why does the first Console::Write give error "indexer needs array or
      >pointer" and the second not?
      >>
      >generic <typename TList, typename ItemTypewhere TList :
      >IList<ItemType >
      >ref class MyClass
      >{
      >public:
      >MyClass() {}
      >void Method(TList list1)
      >{
      >Console::Write ("{0}, ", list1[0]); // error C2109 ??
      >IList<ItemType >^ list2 = list1;
      This line shouldn't have worked -- list1 has stack semantics (tracking
      reference), list2 is a tracking handle. You need an address-of operator to
      make a handle from a reference.

      Maybe changing the formal parameter to a handle "TList^ list1" would resolve
      your problem?
      >Console::Write ("{0}, ", list2[0]); // ok
      >}
      >>
      >};
      >
      I can't figure out why it should be any different, but specifying the
      indexer property explicitly works:
      >
      Console::Write( "{0}, ", list1->default[0]);
      >
      Since there's no real reason why it shouldn't be able to figure out
      the default property when the short form is used (after all, it can do
      it for types which are not generic type parameters just fine!), it's
      probably worth opening a suggestion on VS Connect regarding this.

      Comment

      • christian2.schmidt@gmx.de

        #4
        Re: Indexer on generic argument

        On 7 Aug., 16:47, "Ben Voigt [C++ MVP]" <r...@nospam.no spamwrote:
        Pavel Minaev wrote:
        On Aug 5, 9:22 pm, christian2.schm ...@gmx.de wrote:
        why does the first Console::Write give error "indexer needs array or
        pointer" and the second not?
        >
        generic <typename TList, typename ItemTypewhere TList :
        IList<ItemType>
        ref class MyClass
        {
        public:
        MyClass() {}
        void Method(TList list1)
        {
        Console::Write( "{0}, ", list1[0]); // error C2109 ??
        IList<ItemType> ^ list2 = list1;
        >
        This line shouldn't have worked -- list1 has stack semantics (tracking
        reference), list2 is a tracking handle. You need an address-of operator to
        make a handle from a reference.
        Isn't this some kind of autocasting magic?
        Maybe changing the formal parameter to a handle "TList^ list1" would resolve
        your problem?
        No, this gives error C3229: dereferencing a generic type parameter is
        not allowed.

        Thanks,
        Christian

        Comment

        • Ben Voigt [C++ MVP]

          #5
          Re: Indexer on generic argument

          christian2.schm idt@gmx.de wrote:
          On 7 Aug., 16:47, "Ben Voigt [C++ MVP]" <r...@nospam.no spamwrote:
          >Pavel Minaev wrote:
          >>On Aug 5, 9:22 pm, christian2.schm ...@gmx.de wrote:
          >>>why does the first Console::Write give error "indexer needs array
          >>>or pointer" and the second not?
          >>
          >>>generic <typename TList, typename ItemTypewhere TList :
          >>>IList<ItemTy pe>
          >>>ref class MyClass
          >>>{
          >>>public:
          >>>MyClass() {}
          >>>void Method(TList list1)
          >>>{
          >>>Console::Wri te("{0}, ", list1[0]); // error C2109 ??
          >>>IList<ItemTy pe>^ list2 = list1;
          >>
          >This line shouldn't have worked -- list1 has stack semantics
          >(tracking reference), list2 is a tracking handle. You need an
          >address-of operator to make a handle from a reference.
          >
          Isn't this some kind of autocasting magic?
          >
          >Maybe changing the formal parameter to a handle "TList^ list1" would
          >resolve your problem?
          >
          No, this gives error C3229: dereferencing a generic type parameter is
          not allowed.
          Are you instantiating as MyClass<TListor MyClass<TList^> ?
          >
          Thanks,
          Christian

          Comment

          • Pavel Minaev

            #6
            Re: Indexer on generic argument

            On Aug 7, 6:47 pm, "Ben Voigt [C++ MVP]" <r...@nospam.no spamwrote:
            generic <typename TList, typename ItemTypewhere TList :
            IList<ItemType>
            ref class MyClass
            {
            public:
            MyClass() {}
            void Method(TList list1)
            {
            Console::Write( "{0}, ", list1[0]); // error C2109 ??
            IList<ItemType> ^ list2 = list1;
            >
            This line shouldn't have worked -- list1 has stack semantics (tracking
            reference), list2 is a tracking handle.  You need an address-of operator to
            make a handle from a reference.
            It works because it's a generic declaration, not a template
            declaration. Generic type parameters can only be instantiated with
            handles for ref types - so, for a specific instantiation, TList would
            be something like List<T>^, and not just plain List<T>.

            Comment

            • Ben Voigt [C++ MVP]

              #7
              Re: Indexer on generic argument

              Pavel Minaev wrote:
              On Aug 7, 6:47 pm, "Ben Voigt [C++ MVP]" <r...@nospam.no spamwrote:
              >>>generic <typename TList, typename ItemTypewhere TList :
              >>>IList<ItemTy pe>
              >>>ref class MyClass
              >>>{
              >>>public:
              >>>MyClass() {}
              >>>void Method(TList list1)
              >>>{
              >>>Console::Wri te("{0}, ", list1[0]); // error C2109 ??
              >>>IList<ItemTy pe>^ list2 = list1;
              >>
              >This line shouldn't have worked -- list1 has stack semantics
              >(tracking reference), list2 is a tracking handle. You need an
              >address-of operator to make a handle from a reference.
              >
              It works because it's a generic declaration, not a template
              declaration. Generic type parameters can only be instantiated with
              handles for ref types - so, for a specific instantiation, TList would
              be something like List<T>^, and not just plain List<T>.
              Hmmm. Then the constraint line makes little sense. A tracking handle
              doesn't implement an interface, the type of the referenced object does. I
              realize this is connected to the .NET behavior of following different rules
              when instantiating generics using ref types vs value types, and there
              probably is no perfectly consistent syntax which expresses the behavior.


              Comment

              Working...