3

I am working with the SystemC library which requires all user defined types to have a operator<< and sc_trace() function. However the user defined type is actually a nested type inside a template class, because the "nested type" is computed from the template argument specified in the outer class.

template<typename T>
class Block {
    typedef typename transform<T>::value NewType;
public:
    struct SomeType {
        SomeType() {}
        SomeType(T val) : member(val) {}
        NewType member;
    };
};

When I define the operator<< for SomeType like so

template<typename T>
std::ostream& operator<<(std::ostream& os, const typename Block<T>::SomeType& type) {
    return os << type.member;
}

The compiler cannot deduce the call inside the systemC library that does attempt to dump the nested defined type using the streaming operator. Since I rather not touch the library code (outside my control). Would any one of you experts out there know a way to work around this?

And if there is no clean workaround, would you know if the C++11 has a solution for this?

David KWH
  • 147
  • 8
  • Try making that `typename Block::SomeType const& type`. – ildjarn Apr 09 '12 at 21:36
  • Where have you defined your operator? Have you defined it inside your header `.h` file or your source `.cpp` file? (This makes a difference as far as templates are concerned, although C++11 supports the concept of [extern template](http://stackoverflow.com/questions/6870885/how-to-use-extern-template) ) – Ben Cottrell Apr 09 '12 at 22:03
  • 1
    If you found a solution, please add it in an answer and mark as accepted. – Rafał Rawicki Apr 09 '12 at 22:23
  • I can't answer my own question for 6 hours... hmm. – David KWH Apr 09 '12 at 22:29
  • 1
    "*but with the friend keyword the function takes on global scope*" No it doesn't, it goes in the scope of the enclosing namespace (which may coincidentally happen to be the global scope in _this particular case_). – ildjarn Apr 09 '12 at 22:33
  • Sorry I'm quoting from the book. – David KWH Apr 09 '12 at 22:43
  • The problem is that anytime you have `typename`, you have a non-deducible context. – Xeo Apr 10 '12 at 00:48
  • Seems related: "Template deduction for nested classes | P0293R0": http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0293r0.pdf – Emile Cormier Apr 28 '20 at 21:29

1 Answers1

2

I actually found a solution myself. It is referred to as the Barton-Nackman Trick in Vandevoorde/Josuttis.

The key is to avoid using function template. The standard excludes nested type of a dependent template class from template argument deduction. The operator<< and sc_trace function needs to be defined as a friend function in the template class. This way the function is a non-templated function when the template class is instantiated, but with the friend keyword the function takes on the scope of the enclosing namespace.

David KWH
  • 147
  • 8