How to explicitly instantiate a template class that has a nested class with a friend function (C++)

后端 未结 2 1026
旧时难觅i
旧时难觅i 2021-02-14 11:07

Probably been asked before, but all this is approaching the limit of my comprehension and cognizance of C++, so I\'m a little slow in understanding what\'s being talked about an

2条回答
  •  鱼传尺愫
    2021-02-14 11:33

    For me this should look like this:

    template 
    class Foo
    {
        struct Bar
        {
            template 
            friend void swap(typename Foo::Bar&, typename Foo::Bar&);
        };
    };
    
    template 
    void swap(typename Foo::Bar& b1, typename Foo::Bar& b2) { }
    
    template class Foo;
    
    int main()
    {
       Foo::Bar  bb1, bb2;
       swap(bb1, bb2);
    }  
    

    This runs with gcc: http://ideone.com/zZMYn

    Few notes:

    1. Friend declaration inside the class creates forward declaration of the object that is declared as friend outside of the class. This applies to friend classes, functions, templates. This means that forwards decl of your swap is not needed.

    2. Syntax some-name<..> is used in template specializations and template instantiations. It is not used in forward declarations (including friend declarations) and definitions. In your example you have one forward declaration, one definition and one call (that is an instantiation for templates of the functions).

    If you call the function swap as swap(bb1, bb2);, compiler cannot find it. For me the need to call this function as in the example above swap is more a compiler problem rather than a language requirement. Compiler should deduce template params for template function calls.

    EDIT

    In the example above the vars bb1 and bb2 have type Foo::Bar. This means that the instantiation of swap should be:

    void swap(Foo::Bar &b1, Foo::Bar &b2) { }
    

    No any other instantiation can work here because say Foo::Bar is a different type from Foo::Bar. There is no way to convert Foo::Bar into Foo::Bar. Event if template for Foo::Bar would be instantitated, it cannot be used. The types of params are different.

    If there would be several specializations for this template around, the situation might be more complicated. But at the point of the call there is nothing than the template itself. To be considered, specialization should be visible at the point of the call.

    Excellent compiler might be able to handle this case. Since the work around with explictit type specification is available and seems to work, I would say that the current state of gcc fully Ok.

提交回复
热议问题