Printing the template inner class without template

I have a non type template (like Counted) that points to an instance of a class template (like Counter). Everything works fine as long as both template classes are siblings, like writing a print statement. In the meantime, there is no need to worry about it.

Now for several reasons I want to move the counter inside the counter as an inner class and I cannot write a print statement. In the meantime, there is no need to worry about it.

This is where the "native class version" works with the main code here:

template < class Count >
struct Counter {
    using count_type = Count;
    count_type instances = 0;
};

template < class Cnt, Cnt& c>
struct Counted {
    using id_type = typename Cnt::count_type;
    id_type id;
    Counted() : id(c.instances) { ++c.instances; }
    ~Counted() { --c.instances; }
};

template < class Cnt, Cnt& c >
std::ostream& operator<<(std::ostream& os, Counted<Cnt,c> sib) {
    os << "printing sibling " << sib.id;
    return os;
}

using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = Counted<SCounter, sc>;

      

The version of the "inner class" is not compiled here with the main code here:

template < class Count >
struct Counter {
    using count_type = Count;
    count_type instances = 0;

    template <Counter& c>
    struct Counted {
        using id_type = count_type;
        id_type id;
        Counted() : id(c.instances) { ++c.instances; }
        ~Counted() { --c.instances; }
    };
};

template < class Count, Counter<Count>& c >
std::ostream& operator<<(std::ostream& os,
      typename Counter<Count>::template Counted<c>& sib) {
    os << "printing inner " << sib.id;
    return os;
}

using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = SCounter::Counted<sc>;

      

Errors:

prog.cpp: In function 'int main()':
prog.cpp:32:15: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
  std::cout << j << std::endl;
               ^
In file included from /usr/include/c++/4.9/iostream:39:0,
                 from prog.cpp:1:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Counter<unsigned int>::Counted<(* & sc)>]'
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^

      

Is there a problem in my code, in my compiler, or is it just not allowed by the standard?

+3


source to share


1 answer


Koenig Operators are what you want:

  template <Counter& c>
    struct Counted {
      using id_type = count_type;
      id_type id;
      Counted() : id(c.instances) { ++c.instances; }
      ~Counted() { --c.instances; }

      friend std::ostream& operator<<(
        std::ostream& os,
        Counted const& sib
      ) {
        os << "printing inner " << sib.id;
        return os;
      }           
    };
};

      



here we create friend operator<<

. It will be found via ADL (or Koenig search) when trying to use <<

with an instance Counted

.

Another function is created and Counted

no pattern subtraction is performed for each type .

+1


source







All Articles